@yumiai/chat-widget 0.1.2 → 0.2.1
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/CHANGELOG.md +100 -0
- package/README.md +119 -22
- package/dist/ExcelCore-DJOIVQMI.js +11 -0
- package/dist/ExcelCore-DJOIVQMI.js.map +1 -0
- package/dist/ExcelViewer-3YLLYYIQ.js +65 -0
- package/dist/ExcelViewer-3YLLYYIQ.js.map +1 -0
- package/dist/GerberViewerA2UI-7CNT7HX4.css +693 -0
- package/dist/GerberViewerA2UI-7CNT7HX4.css.map +1 -0
- package/dist/GerberViewerA2UI-X5FWAD5M.js +57 -0
- package/dist/GerberViewerA2UI-X5FWAD5M.js.map +1 -0
- package/dist/GraphStatsLegend-D5bPeXB_.d.cts +607 -0
- package/dist/GraphStatsLegend-D5bPeXB_.d.ts +607 -0
- package/dist/JsonRenderStandalone-EIZM62JU.js +18 -0
- package/dist/JsonRenderStandalone-EIZM62JU.js.map +1 -0
- package/dist/JsonRenderStandalone-POB4Q3N3.css +2384 -0
- package/dist/JsonRenderStandalone-POB4Q3N3.css.map +1 -0
- package/dist/JsonRenderStandalone-UsTcST4G.d.cts +23 -0
- package/dist/JsonRenderStandalone-UsTcST4G.d.ts +23 -0
- package/dist/KicadViewer-GV6ZC4AQ.js +124 -0
- package/dist/KicadViewer-GV6ZC4AQ.js.map +1 -0
- package/dist/KicadViewerCore-U7BWZHKJ.js +11 -0
- package/dist/KicadViewerCore-U7BWZHKJ.js.map +1 -0
- package/dist/PdfViewer-CHPDRK46.js +51 -0
- package/dist/PdfViewer-CHPDRK46.js.map +1 -0
- package/dist/PdfViewer-LPYGQETK.css +1899 -0
- package/dist/PdfViewer-LPYGQETK.css.map +1 -0
- package/dist/PdfViewerCore-HJPEHSRA.js +364 -0
- package/dist/PdfViewerCore-HJPEHSRA.js.map +1 -0
- package/dist/PowerPointCore-FPDR2BL4.js +11 -0
- package/dist/PowerPointCore-FPDR2BL4.js.map +1 -0
- package/dist/PowerPointViewer-LQTO6UCU.js +61 -0
- package/dist/PowerPointViewer-LQTO6UCU.js.map +1 -0
- package/dist/StepViewerCore-7W3L3R4E.js +285 -0
- package/dist/StepViewerCore-7W3L3R4E.js.map +1 -0
- package/dist/ThreeViewerCore-N3QJD5QI.js +161 -0
- package/dist/ThreeViewerCore-N3QJD5QI.js.map +1 -0
- package/dist/WordCore-JKSXK2XD.js +11 -0
- package/dist/WordCore-JKSXK2XD.js.map +1 -0
- package/dist/WordViewer-ZHCQMHOH.js +61 -0
- package/dist/WordViewer-ZHCQMHOH.js.map +1 -0
- package/dist/chunk-2SKA3F5U.js +88 -0
- package/dist/chunk-2SKA3F5U.js.map +1 -0
- package/dist/chunk-2UC7YLVX.js +318 -0
- package/dist/chunk-2UC7YLVX.js.map +1 -0
- package/dist/chunk-3R6T3LBR.js +24 -0
- package/dist/chunk-3R6T3LBR.js.map +1 -0
- package/dist/chunk-56WRZM3R.js +398 -0
- package/dist/chunk-56WRZM3R.js.map +1 -0
- package/dist/chunk-7A4FY6FK.js +10226 -0
- package/dist/chunk-7A4FY6FK.js.map +1 -0
- package/dist/chunk-7D4SUZUM.js +38 -0
- package/dist/chunk-7D4SUZUM.js.map +1 -0
- package/dist/chunk-7S67DOHQ.js +436 -0
- package/dist/chunk-7S67DOHQ.js.map +1 -0
- package/dist/chunk-CFKGNAJM.js +14013 -0
- package/dist/chunk-CFKGNAJM.js.map +1 -0
- package/dist/chunk-GAMA3VA7.js +99 -0
- package/dist/chunk-GAMA3VA7.js.map +1 -0
- package/dist/chunk-GYXTSY22.js +639 -0
- package/dist/chunk-GYXTSY22.js.map +1 -0
- package/dist/chunk-K4KGNVL5.js +77 -0
- package/dist/chunk-K4KGNVL5.js.map +1 -0
- package/dist/chunk-KQV7IKET.js +1621 -0
- package/dist/chunk-KQV7IKET.js.map +1 -0
- package/dist/chunk-O3NXUM6C.js +1871 -0
- package/dist/chunk-O3NXUM6C.js.map +1 -0
- package/dist/chunk-PZXSASDY.js +83 -0
- package/dist/chunk-PZXSASDY.js.map +1 -0
- package/dist/chunk-QLVPIM6R.js +595 -0
- package/dist/chunk-QLVPIM6R.js.map +1 -0
- package/dist/chunk-VXJWGLZ7.js +21 -0
- package/dist/chunk-VXJWGLZ7.js.map +1 -0
- package/dist/chunk-XQ562W7I.js +116 -0
- package/dist/chunk-XQ562W7I.js.map +1 -0
- package/dist/components/JsonRender/standalone.cjs +39368 -0
- package/dist/components/JsonRender/standalone.cjs.map +1 -0
- package/dist/components/JsonRender/standalone.css +2384 -0
- package/dist/components/JsonRender/standalone.css.map +1 -0
- package/dist/components/JsonRender/standalone.d.cts +16 -0
- package/dist/components/JsonRender/standalone.d.ts +16 -0
- package/dist/components/JsonRender/standalone.js +38 -0
- package/dist/components/JsonRender/standalone.js.map +1 -0
- package/dist/gerber-2d-entry-OQ4SQRBY.js +3950 -0
- package/dist/gerber-2d-entry-OQ4SQRBY.js.map +1 -0
- package/dist/gerber-3d-entry-DEHDBOO2.js +3679 -0
- package/dist/gerber-3d-entry-DEHDBOO2.js.map +1 -0
- package/dist/gerber-simulation-entry-EBDX72XE.js +1801 -0
- package/dist/gerber-simulation-entry-EBDX72XE.js.map +1 -0
- package/dist/index.cjs +60113 -2970
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +11342 -1708
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +3275 -77
- package/dist/index.d.ts +3275 -77
- package/dist/index.js +18078 -2540
- package/dist/index.js.map +1 -1
- package/dist/provenance/index.cjs +2248 -0
- package/dist/provenance/index.cjs.map +1 -0
- package/dist/provenance/index.css +52 -0
- package/dist/provenance/index.css.map +1 -0
- package/dist/provenance/index.d.cts +12 -0
- package/dist/provenance/index.d.ts +12 -0
- package/dist/provenance/index.js +27 -0
- package/dist/provenance/index.js.map +1 -0
- package/dist/resolveToArrayBuffer-AQIDZHSQ.js +23 -0
- package/dist/resolveToArrayBuffer-AQIDZHSQ.js.map +1 -0
- package/package.json +98 -17
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/FileViewer/viewers/GerberViewer.tsx","../src/components/jetPaveGerberViewer/src/pages/Page2D.tsx","../src/components/jetPaveGerberViewer/src/pages/Page3D.tsx","../src/components/jetPaveGerberViewer/src/legacy/bootLegacyLoad.ts","../src/components/jetPaveGerberViewer/src/pages/PageSimulation.tsx"],"sourcesContent":["import React, { useEffect, useRef, useState } from 'react'\nimport type { ResourceContent } from '../../../types.js'\nimport { Page2D } from '../../jetPaveGerberViewer/src/pages/Page2D'\nimport type { GerberLayerSelectPayload } from '../../jetPaveGerberViewer/src/pages/Page2D'\nimport { Page3D } from '../../jetPaveGerberViewer/src/pages/Page3D'\nimport { PageSimulation } from '../../jetPaveGerberViewer/src/pages/PageSimulation'\n\nexport type { GerberLayerSelectPayload }\nexport type GerberViewMode = '2d' | '3d' | 'simulation'\n\nconst ALL_MODES: readonly GerberViewMode[] = ['2d', '3d', 'simulation'] as const\nconst MODE_LABEL: Record<GerberViewMode, string> = {\n '2d': '2D模式',\n '3d': '3D模式',\n simulation: '仿真图',\n}\n\n/**\n * CWRF-013 Phase 0 PR #3 — Core viewer public API.\n *\n * Backward-compatible dual-mode API following the React standard\n * `value` / `defaultValue` convention:\n * - omit both `mode` + `defaultMode` ⇒ uncontrolled, initial '2d'\n * (original behaviour preserved for chat-widget-external consumers)\n * - pass `defaultMode` only ⇒ uncontrolled, initial == `defaultMode`,\n * user may still flip via the internal toggle bar\n * - pass `mode` ⇒ controlled. Core does NOT manage internal state; the\n * toggle bar becomes read-only (disabled buttons, aria-disabled,\n * tabIndex=-1) so the parent (Agent/A2UI) owns the truth. `onModeChange`\n * still fires when buttons are clicked so consumers can intercept.\n *\n * Design ref: docs/proposals/CWRF-013-a2ui-systematic-upgrade/02_protocol_honesty/03_gerber_viewer_mode.md v1.1 §2.1\n */\nexport interface GerberViewerProps {\n content?: ResourceContent\n url?: string\n onGerberSelection?: (payload: GerberLayerSelectPayload) => void\n /** Controlled mode. When provided, internal state is bypassed and the toggle bar becomes read-only. */\n mode?: GerberViewMode\n /** Uncontrolled initial mode. Ignored when `mode` is provided. Default: '2d'. */\n defaultMode?: GerberViewMode\n /** Fired whenever the mode changes (user click in uncontrolled mode, or attempted click in controlled mode). */\n onModeChange?: (next: GerberViewMode) => void\n}\n\nconst GerberViewer: React.FC<GerberViewerProps> = ({\n content,\n url,\n onGerberSelection,\n mode: controlledMode,\n defaultMode = '2d',\n onModeChange,\n}) => {\n const isControlled = controlledMode !== undefined\n const [internalMode, setInternalMode] = useState<GerberViewMode>(defaultMode)\n const mode: GerberViewMode = isControlled ? controlledMode : internalMode\n\n // Surface controlled-value changes via onModeChange so parents that need\n // to react (telemetry, ActionBinding echo) get one callback per actual change.\n const lastReportedRef = useRef<GerberViewMode>(mode)\n useEffect(() => {\n if (!isControlled) return\n if (lastReportedRef.current === mode) return\n lastReportedRef.current = mode\n onModeChange?.(mode)\n }, [isControlled, mode, onModeChange])\n\n const handleModeClick = (next: GerberViewMode) => {\n if (!isControlled) {\n setInternalMode(next)\n lastReportedRef.current = next\n }\n onModeChange?.(next)\n }\n\n return (\n <div\n className=\"ycw-file-viewer-gerber ycw-file-viewer-gerber-embedded\"\n data-mode={mode}\n >\n <div\n className=\"ycw-gerber-mode-bar\"\n data-controlled={isControlled ? 'true' : undefined}\n role={isControlled ? 'group' : undefined}\n aria-label={isControlled ? 'Gerber view mode (controlled)' : undefined}\n >\n {ALL_MODES.map((m) => (\n <button\n key={m}\n type=\"button\"\n className={`viewer-action-btn${mode === m ? ' active' : ''}`}\n onClick={() => handleModeClick(m)}\n disabled={isControlled}\n aria-disabled={isControlled || undefined}\n tabIndex={isControlled ? -1 : 0}\n data-active={mode === m ? 'true' : undefined}\n >\n {MODE_LABEL[m]}\n </button>\n ))}\n </div>\n\n <div className=\"ycw-gerber-viewer-body\">\n {mode === '2d' && <Page2D content={content} url={url} onLayerSelect={onGerberSelection} />}\n {mode === '3d' && <Page3D content={content} url={url} />}\n {mode === 'simulation' && <PageSimulation content={content} url={url} />}\n </div>\n </div>\n )\n}\n\nexport default GerberViewer\n","import { useEffect, useRef, useState } from 'react'\nimport type { ResourceContent } from '../../../../types.js'\nimport '../styles/page-2d.css'\n\nexport interface GerberLayerSelectPayload {\n snippet: string\n anchorRect: { top: number; left: number } | null\n}\n\nexport interface Page2DProps {\n content?: ResourceContent\n url?: string\n onLayerSelect?: (payload: GerberLayerSelectPayload) => void\n}\n\n// ── HMR-safe persistent state (stored on window to survive module re-evaluation) ──\n\nconst WIN = window as unknown as Record<string, unknown>\nconst CONTAINER_KEY = '__gerber2d_container__'\nconst READY_KEY = '__gerber2d_ready__'\n\nfunction getOrCreateContainer(): HTMLDivElement {\n const existing = WIN[CONTAINER_KEY] as HTMLDivElement | undefined\n if (existing) return existing\n\n // New container — any previously-cached module holds stale DOM refs, force re-import\n delete WIN[READY_KEY]\n\n const el = document.createElement('div')\n el.className = 'layout-2d'\n el.innerHTML = `\n<div id=\"loadingOverlay\">正在处理中...</div>\n<div class=\"container\">\n <div class=\"controls\" style=\"display:none\">\n <div class=\"file-input-wrapper\">\n <input type=\"file\" id=\"fileInput\"\n accept=\".zip,.rar,.gtl,.gbl,.gts,.gbs,.gto,.gbo,.gtp,.gbp,.gm1,.drl,.gbr,.gko,.txt,.tx1,.g1,.g2,.g3,.g4,.g5,.g6,.gp1,.gp2,.gp3\"\n multiple />\n </div>\n <div class=\"file-info\" id=\"fileInfo\" style=\"display:none\">\n <div class=\"file-name\" id=\"fileName\"></div>\n <div id=\"fileSize\"></div>\n </div>\n <div class=\"status\" id=\"status\" style=\"display:none\"></div>\n </div>\n <div class=\"viewer\">\n <div class=\"viewer-content\">\n <div class=\"webgl-canvas-container\">\n <canvas id=\"canvas\"></canvas>\n </div>\n <div class=\"layer-list-container\">\n <div class=\"layer-list-title\">图层列表</div>\n <div class=\"layer-list-header\">\n <div class=\"layer-toggle-all\" id=\"layerToggleAll\">\n <div class=\"layer-toggle checked\" id=\"layerToggleAllCheckbox\"></div>\n <span class=\"layer-toggle-all-label\">全部显示/隐藏</span>\n </div>\n </div>\n <div class=\"layer-list\" id=\"layerList\"></div>\n </div>\n </div>\n </div>\n</div>`\n\n WIN[CONTAINER_KEY] = el\n return el\n}\n\nfunction isViewerReady(): boolean {\n return !!WIN[READY_KEY]\n}\nfunction markViewerReady(): void {\n WIN[READY_KEY] = true\n}\n\n// ── Data injection helpers ──────────────────────────────────────────────────\n\nfunction injectFile(file: File): void {\n const container = WIN[CONTAINER_KEY] as HTMLDivElement | undefined\n const fi = container?.querySelector<HTMLInputElement>('#fileInput')\n if (!fi) throw new Error('#fileInput not found in persistent container')\n\n console.log('[Page2D] injectFile: element found, isConnected =', fi.isConnected, ', file =', file.name, file.size)\n\n const dt = new DataTransfer()\n dt.items.add(file)\n fi.files = dt.files\n\n console.log('[Page2D] injectFile: files set, count =', fi.files.length, ', dispatching change...')\n\n const testListener = () => console.log('[Page2D] injectFile: ✓ change event received by test listener')\n fi.addEventListener('change', testListener, { once: true })\n\n const handled = fi.dispatchEvent(new Event('change', { bubbles: true }))\n console.log('[Page2D] injectFile: change dispatched, defaultPrevented =', !handled)\n\n fi.removeEventListener('change', testListener)\n}\n\nasync function fetchAndInject(url: string): Promise<void> {\n const res = await fetch(url)\n if (!res.ok) throw new Error(`Fetch failed: HTTP ${res.status}`)\n const blob = await res.blob()\n\n let name = 'gerber.zip'\n try {\n const seg = new URL(url).pathname.split('/').filter(Boolean).pop()\n if (seg) name = decodeURIComponent(seg)\n } catch { /* keep default name */ }\n\n const hdr = new Uint8Array(await blob.slice(0, 4).arrayBuffer())\n const isZip = hdr[0] === 0x50 && hdr[1] === 0x4b\n const isRar = hdr[0] === 0x52 && hdr[1] === 0x61 && hdr[2] === 0x72\n\n if (isZip && !name.toLowerCase().endsWith('.zip'))\n name = name.replace(/\\.[^.]+$/, '') + '.zip'\n if (isRar && !name.toLowerCase().endsWith('.rar'))\n name = name.replace(/\\.[^.]+$/, '') + '.rar'\n\n const type = isZip\n ? 'application/zip'\n : isRar\n ? 'application/x-rar-compressed'\n : blob.type || 'application/octet-stream'\n\n injectFile(new File([blob], name, { type }))\n}\n\n// ── Component ───────────────────────────────────────────────────────────────\n\nexport function Page2D({ content, url, onLayerSelect }: Page2DProps) {\n const mountRef = useRef<HTMLDivElement>(null)\n const [error, setError] = useState<string | null>(null)\n const onLayerSelectRef = useRef(onLayerSelect)\n onLayerSelectRef.current = onLayerSelect\n\n useEffect(() => {\n const mount = mountRef.current\n if (!mount) return\n const container = getOrCreateContainer()\n mount.appendChild(container)\n\n if (isViewerReady()) {\n window.dispatchEvent(new Event('resize'))\n }\n\n const handleLayerClick = (e: MouseEvent) => {\n const cb = onLayerSelectRef.current\n if (!cb) return\n\n const item = (e.target as HTMLElement).closest?.('.layer-item') as HTMLElement | null\n if (!item) return\n\n const nameEl = item.querySelector('.layer-name')\n const layerName = nameEl?.textContent?.trim()\n if (!layerName) return\n\n const rect = item.getBoundingClientRect()\n const mountRect = mount.getBoundingClientRect()\n\n cb({\n snippet: `[Gerber 图层] ${layerName}`,\n anchorRect: {\n top: rect.bottom - mountRect.top + 4,\n left: rect.left - mountRect.left + rect.width / 2,\n },\n })\n }\n\n container.addEventListener('click', handleLayerClick)\n\n return () => {\n container.removeEventListener('click', handleLayerClick)\n if (container.parentNode === mount) mount.removeChild(container)\n }\n }, [])\n\n useEffect(() => {\n let cancelled = false\n\n void (async () => {\n try {\n setError(null)\n\n if (!isViewerReady()) {\n console.log('[Page2D] importing 2d entry module...')\n await import('../viewer-src/2dPage/js/gerber-2d-entry.js')\n markViewerReady()\n console.log('[Page2D] module imported, checking DOM elements:', {\n canvas: !!document.getElementById('canvas'),\n fileInput: !!document.getElementById('fileInput'),\n containerInDOM: !!(WIN[CONTAINER_KEY] as HTMLElement)?.isConnected,\n })\n } else {\n console.log('[Page2D] viewer already ready, skipping import')\n }\n if (cancelled) return\n\n await new Promise<void>((r) => requestAnimationFrame(() => r()))\n if (cancelled) return\n\n console.log('[Page2D] inject check', {\n hasContent: !!content,\n contentUrl: content?.content_url,\n contentLength: content?.content?.length,\n fileName: content?.file_name,\n url,\n content:content\n })\n\n if (content?.content_url) {\n console.log('[Page2D] fetchAndInject via content_url')\n await fetchAndInject(content.content_url)\n } else if (\n typeof content?.content === 'string' &&\n content.content.trim()\n ) {\n console.log('[Page2D] injectFile from content string, length =', content.content.length)\n injectFile(\n new File([content.content], content.file_name || 'board.gbr', {\n type: content.mime_type || 'text/plain',\n }),\n )\n } else if (url) {\n console.log('[Page2D] fetchAndInject via url prop')\n await fetchAndInject(url)\n } else {\n console.warn('[Page2D] no data to inject — content and url are both empty')\n }\n } catch (err) {\n if (!cancelled) {\n console.error('[Page2D]', err)\n setError(err instanceof Error ? err.message : String(err))\n }\n }\n })()\n\n return () => {\n cancelled = true\n }\n }, [content?.resource_id, content?.content_url, content?.content, content?.file_name, url])\n\n return (\n <div ref={mountRef} className=\"layout-2d-mount\">\n {error && (\n <div className=\"layout-2d-error\">Gerber 查看器加载失败: {error}</div>\n )}\n </div>\n )\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { ResourceContent } from '../../../../types.js'\nimport { importAndBootLoad } from '../legacy/bootLegacyLoad'\nimport '../styles/page-3d.css'\n\nexport interface Page3DProps {\n content?: ResourceContent\n url?: string\n}\n\n// ── HMR-safe persistent state ───────────────────────────────────────────────\n\nconst WIN = window as unknown as Record<string, unknown>\nconst CONTAINER_KEY = '__gerber3d_container__'\nconst READY_KEY = '__gerber3d_ready__'\n\nfunction getOrCreateContainer(): HTMLDivElement {\n const existing = WIN[CONTAINER_KEY] as HTMLDivElement | undefined\n if (existing) return existing\n\n delete WIN[READY_KEY]\n\n const el = document.createElement('div')\n el.className = 'layout-3d'\n el.innerHTML = `\n<div id=\"viewer3d-canvas-host\" class=\"viewer3d-canvas-host\"></div>\n<input type=\"file\" id=\"file-input\" class=\"file-input\" style=\"display:none\"\n multiple accept=\".zip,.rar,.gbr,.gtl,.gbl,.gko,.gm1,.drl,.out,.txt\" />\n<div id=\"gerber-3d-toolbar\"\n style=\"position:absolute;top:10px;left:10px;z-index:200;\n background:rgba(0,0,0,0.7);color:#fff;padding:10px;border-radius:5px;\n display:flex;flex-direction:column;gap:8px;\">\n <p style=\"font-size:12px;margin:0;color:#ccc;\">左键旋转 | 右键平移 | 滚轮缩放</p>\n <div id=\"stats\" style=\"font-size:12px;\"></div>\n</div>\n<div id=\"info\"></div>\n<div id=\"loading\">正在处理...</div>`\n\n WIN[CONTAINER_KEY] = el\n return el\n}\n\nfunction isViewerReady(): boolean {\n return !!WIN[READY_KEY]\n}\nfunction markViewerReady(): void {\n WIN[READY_KEY] = true\n}\n\n// ── Data injection ──────────────────────────────────────────────────────────\n\nfunction injectFile(file: File): void {\n const container = WIN[CONTAINER_KEY] as HTMLDivElement | undefined\n const fi = container?.querySelector<HTMLInputElement>('#file-input')\n if (!fi) throw new Error('#file-input not found in persistent container')\n const dt = new DataTransfer()\n dt.items.add(file)\n fi.files = dt.files\n fi.dispatchEvent(new Event('change', { bubbles: true }))\n}\n\nasync function fetchAndInject(url: string): Promise<void> {\n const res = await fetch(url)\n if (!res.ok) throw new Error(`Fetch failed: HTTP ${res.status}`)\n const blob = await res.blob()\n\n let name = 'gerber.zip'\n try {\n const seg = new URL(url).pathname.split('/').filter(Boolean).pop()\n if (seg) name = decodeURIComponent(seg)\n } catch { /* keep default name */ }\n\n const hdr = new Uint8Array(await blob.slice(0, 4).arrayBuffer())\n const isZip = hdr[0] === 0x50 && hdr[1] === 0x4b\n const isRar = hdr[0] === 0x52 && hdr[1] === 0x61 && hdr[2] === 0x72\n\n if (isZip && !name.toLowerCase().endsWith('.zip'))\n name = name.replace(/\\.[^.]+$/, '') + '.zip'\n if (isRar && !name.toLowerCase().endsWith('.rar'))\n name = name.replace(/\\.[^.]+$/, '') + '.rar'\n\n const type = isZip\n ? 'application/zip'\n : isRar\n ? 'application/x-rar-compressed'\n : blob.type || 'application/octet-stream'\n\n injectFile(new File([blob], name, { type }))\n}\n\n// ── Component ───────────────────────────────────────────────────────────────\n\nexport function Page3D({ content, url }: Page3DProps) {\n const mountRef = useRef<HTMLDivElement>(null)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n const mount = mountRef.current\n if (!mount) return\n const container = getOrCreateContainer()\n mount.appendChild(container)\n\n if (isViewerReady()) {\n window.dispatchEvent(new Event('resize'))\n }\n\n return () => {\n if (container.parentNode === mount) mount.removeChild(container)\n }\n }, [])\n\n useEffect(() => {\n let cancelled = false\n\n void (async () => {\n try {\n setError(null)\n\n if (!isViewerReady()) {\n await importAndBootLoad(\n () => import('../viewer-src/3dPage/js/gerber-3d-entry.js'),\n )\n markViewerReady()\n }\n if (cancelled) return\n\n await new Promise<void>((r) => requestAnimationFrame(() => r()))\n if (cancelled) return\n\n window.dispatchEvent(new Event('resize'))\n\n console.log('[Page3D] inject check', {\n hasContent: !!content,\n contentUrl: content?.content_url,\n contentLength: content?.content?.length,\n fileName: content?.file_name,\n url,\n })\n\n if (content?.content_url) {\n console.log('[Page3D] fetchAndInject via content_url')\n await fetchAndInject(content.content_url)\n } else if (\n typeof content?.content === 'string' &&\n content.content.trim()\n ) {\n console.log('[Page3D] injectFile from content string, length =', content.content.length)\n injectFile(\n new File([content.content], content.file_name || 'board.gbr', {\n type: content.mime_type || 'text/plain',\n }),\n )\n } else if (url) {\n console.log('[Page3D] fetchAndInject via url prop')\n await fetchAndInject(url)\n } else {\n console.warn('[Page3D] no data to inject — content and url are both empty')\n }\n } catch (err) {\n if (!cancelled) {\n console.error('[Page3D]', err)\n setError(err instanceof Error ? err.message : String(err))\n }\n }\n })()\n\n return () => {\n cancelled = true\n }\n }, [content?.resource_id, content?.content_url, content?.content, content?.file_name, url])\n\n return (\n <div ref={mountRef} className=\"layout-3d-mount\">\n {error && (\n <div className=\"layout-3d-error\">3D 查看器加载失败: {error}</div>\n )}\n </div>\n )\n}\n","/**\n * 原版 2d/3d main 在 window.load / window.onload 里初始化。\n * React 动态 import 往往在 document 已 complete 之后才结束,需补发一次 load。\n */\nexport function fireLoadIfAlreadyComplete(): void {\n if (document.readyState === 'complete') {\n window.dispatchEvent(new Event('load'))\n }\n}\n\nexport async function importAndBootLoad(importer: () => Promise<unknown>): Promise<void> {\n await importer()\n fireLoadIfAlreadyComplete()\n}\n","import { useEffect, useRef, useState } from 'react'\nimport type { ResourceContent } from '../../../../types.js'\nimport '../styles/page-simulation.css'\n\nexport interface PageSimulationProps {\n content?: ResourceContent\n url?: string\n}\n\n// ── HMR-safe persistent state ───────────────────────────────────────────────\n\nconst WIN = window as unknown as Record<string, unknown>\nconst CONTAINER_KEY = '__gerberSim_container__'\nconst READY_KEY = '__gerberSim_ready__'\n\nfunction getOrCreateContainer(): HTMLDivElement {\n const existing = WIN[CONTAINER_KEY] as HTMLDivElement | undefined\n if (existing) return existing\n\n delete WIN[READY_KEY]\n\n const el = document.createElement('div')\n el.className = 'layout-simulation'\n el.innerHTML = `\n<div class=\"container\">\n <div class=\"control-panel\">\n <h2 class=\"panel-title\">仿真图</h2>\n\n <div class=\"control-group\" style=\"display:none\">\n <div class=\"file-input-wrapper\">\n <span class=\"file-input-button\">📁 选择 Gerber 文件</span>\n <input type=\"file\" id=\"fileInput\"\n accept=\".zip,.rar,.gbr,.gtl,.gbl,.gts,.gbs,.gto,.gbo,.gtp,.gbp,.gko,.drl,.txt\"\n multiple />\n </div>\n </div>\n\n <div class=\"control-group\">\n <div class=\"control-label\">查看面</div>\n <div class=\"view-toggle\">\n <button type=\"button\" id=\"btnTopView\" class=\"active\">顶层 (Top)</button>\n <button type=\"button\" id=\"btnBottomView\">底层 (Bottom)</button>\n </div>\n </div>\n\n <div class=\"control-group\">\n <div class=\"control-row\">\n <span class=\"control-label\">阻焊颜色</span>\n <div class=\"color-preview\">\n <div class=\"color-swatch\" id=\"maskColorPreview\" style=\"background:#1C590B\"></div>\n <select id=\"maskColorSelect\">\n <option value=\"#1C590B\" selected>绿色</option>\n <option value=\"#1a3a6e\">蓝色</option>\n <option value=\"#8b0000\">红色</option>\n <option value=\"#1a1a1a\">黑色</option>\n <option value=\"#f5f5f5\">白色</option>\n <option value=\"#2d2d2d\">哑光黑</option>\n <option value=\"#4a0080\">紫色</option>\n <option value=\"#c4a000\">黄色</option>\n </select>\n </div>\n </div>\n </div>\n\n <div class=\"control-group\">\n <div class=\"control-row\">\n <span class=\"control-label\">丝印颜色</span>\n <div class=\"color-preview\">\n <div class=\"color-swatch\" id=\"silkColorPreview\" style=\"background:#ffffff\"></div>\n <select id=\"silkColorSelect\">\n <option value=\"#ffffff\" selected>白色</option>\n <option value=\"#000000\">黑色</option>\n <option value=\"#f5e642\">黄色</option>\n </select>\n </div>\n </div>\n </div>\n\n <div class=\"control-group\">\n <div class=\"control-row\">\n <span class=\"control-label\">表面处理</span>\n <div class=\"color-preview\">\n <div class=\"color-swatch\" id=\"finishColorPreview\" style=\"background:#D4AF37\"></div>\n <select id=\"finishSelect\">\n <option value=\"ENIG\" selected>沉金 (ENIG)</option>\n <option value=\"HASL\">喷锡 (HASL)</option>\n <option value=\"OSP\">OSP</option>\n <option value=\"SILVER\">镀银</option>\n <option value=\"ENEPIG\">化镍钯金</option>\n </select>\n </div>\n </div>\n </div>\n\n <div class=\"control-group\">\n <div class=\"switch-row\">\n <span class=\"control-label\">显示阻焊层</span>\n <label class=\"switch\"><input type=\"checkbox\" id=\"showMask\" checked /><span class=\"slider\"></span></label>\n </div>\n <div class=\"switch-row\">\n <span class=\"control-label\">显示丝印层</span>\n <label class=\"switch\"><input type=\"checkbox\" id=\"showSilk\" checked /><span class=\"slider\"></span></label>\n </div>\n <div class=\"switch-row\">\n <span class=\"control-label\">显示钻孔</span>\n <label class=\"switch\"><input type=\"checkbox\" id=\"showDrill\" checked /><span class=\"slider\"></span></label>\n </div>\n </div>\n\n <div class=\"control-group\" style=\"margin-top:auto\">\n <button type=\"button\" class=\"btn btn-success\" id=\"btnExport\">📷 导出仿真图</button>\n <button type=\"button\" class=\"btn btn-secondary\" id=\"btnClear\">🗑️ 清空</button>\n </div>\n\n </div>\n\n <div class=\"main-view\">\n <div class=\"canvas-container\" id=\"canvasContainer\">\n <canvas id=\"simulationCanvas\"></canvas>\n <div class=\"loading-overlay hidden\" id=\"loadingOverlay\">\n <div class=\"spinner\"></div>\n <div class=\"loading-text\" id=\"loadingText\">正在解析文件...</div>\n </div>\n </div>\n <div class=\"hidden-status\">\n <span id=\"statusLeft\"></span>\n <span id=\"statusRight\"></span>\n <div id=\"layerList\"></div>\n </div>\n </div>\n</div>`\n\n WIN[CONTAINER_KEY] = el\n return el\n}\n\nfunction isViewerReady(): boolean {\n return !!WIN[READY_KEY]\n}\nfunction markViewerReady(): void {\n WIN[READY_KEY] = true\n}\n\n// ── Data injection ──────────────────────────────────────────────────────────\n\nfunction injectFile(file: File): void {\n const container = WIN[CONTAINER_KEY] as HTMLDivElement | undefined\n const fi = container?.querySelector<HTMLInputElement>('#fileInput')\n if (!fi) throw new Error('#fileInput not found in persistent container')\n const dt = new DataTransfer()\n dt.items.add(file)\n fi.files = dt.files\n fi.dispatchEvent(new Event('change', { bubbles: true }))\n}\n\nasync function fetchAndInject(url: string): Promise<void> {\n const res = await fetch(url)\n if (!res.ok) throw new Error(`Fetch failed: HTTP ${res.status}`)\n const blob = await res.blob()\n\n let name = 'gerber.zip'\n try {\n const seg = new URL(url).pathname.split('/').filter(Boolean).pop()\n if (seg) name = decodeURIComponent(seg)\n } catch { /* keep default name */ }\n\n const hdr = new Uint8Array(await blob.slice(0, 4).arrayBuffer())\n const isZip = hdr[0] === 0x50 && hdr[1] === 0x4b\n const isRar = hdr[0] === 0x52 && hdr[1] === 0x61 && hdr[2] === 0x72\n\n if (isZip && !name.toLowerCase().endsWith('.zip'))\n name = name.replace(/\\.[^.]+$/, '') + '.zip'\n if (isRar && !name.toLowerCase().endsWith('.rar'))\n name = name.replace(/\\.[^.]+$/, '') + '.rar'\n\n const type = isZip\n ? 'application/zip'\n : isRar\n ? 'application/x-rar-compressed'\n : blob.type || 'application/octet-stream'\n\n injectFile(new File([blob], name, { type }))\n}\n\n// ── Component ───────────────────────────────────────────────────────────────\n\nexport function PageSimulation({ content, url }: PageSimulationProps) {\n const mountRef = useRef<HTMLDivElement>(null)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n const mount = mountRef.current\n if (!mount) return\n const container = getOrCreateContainer()\n mount.appendChild(container)\n\n if (isViewerReady()) {\n window.dispatchEvent(new Event('resize'))\n }\n\n return () => {\n if (container.parentNode === mount) mount.removeChild(container)\n }\n }, [])\n\n useEffect(() => {\n let cancelled = false\n\n void (async () => {\n try {\n setError(null)\n\n if (!isViewerReady()) {\n await import('../viewer-src/simulation/js/gerber-simulation-entry.js')\n markViewerReady()\n }\n if (cancelled) return\n\n await new Promise<void>((r) => requestAnimationFrame(() => r()))\n if (cancelled) return\n\n window.dispatchEvent(new Event('resize'))\n\n console.log('[PageSimulation] inject check', {\n hasContent: !!content,\n contentUrl: content?.content_url,\n contentLength: content?.content?.length,\n fileName: content?.file_name,\n url,\n })\n\n if (content?.content_url) {\n console.log('[PageSimulation] fetchAndInject via content_url')\n await fetchAndInject(content.content_url)\n } else if (\n typeof content?.content === 'string' &&\n content.content.trim()\n ) {\n console.log('[PageSimulation] injectFile from content string, length =', content.content.length)\n injectFile(\n new File([content.content], content.file_name || 'board.gbr', {\n type: content.mime_type || 'text/plain',\n }),\n )\n } else if (url) {\n console.log('[PageSimulation] fetchAndInject via url prop')\n await fetchAndInject(url)\n } else {\n console.warn('[PageSimulation] no data to inject — content and url are both empty')\n }\n } catch (err) {\n if (!cancelled) {\n console.error('[PageSimulation]', err)\n setError(err instanceof Error ? err.message : String(err))\n }\n }\n })()\n\n return () => {\n cancelled = true\n }\n }, [content?.resource_id, content?.content_url, content?.content, content?.file_name, url])\n\n return (\n <div ref={mountRef} className=\"layout-simulation-mount\">\n {error && (\n <div className=\"layout-simulation-error\">仿真查看器加载失败: {error}</div>\n )}\n </div>\n )\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","useEffect","useRef","useState","jsx","jsxs","WIN","CONTAINER_KEY","READY_KEY","getOrCreateContainer","isViewerReady","markViewerReady","injectFile","fetchAndInject","useRef","useState","useEffect","useEffect","useRef","useState","jsx","jsxs","WIN","CONTAINER_KEY","READY_KEY","getOrCreateContainer","isViewerReady","markViewerReady","injectFile","fetchAndInject","useRef","useState","useEffect","jsx","jsxs","useState","useRef","useEffect"]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useRevokeBlobUrl
|
|
3
|
+
} from "./chunk-VXJWGLZ7.js";
|
|
4
|
+
|
|
5
|
+
// src/components/ViewerCore/WordCore.tsx
|
|
6
|
+
import { useRef, useEffect, useState, useCallback } from "react";
|
|
7
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
var WordCore = ({ src, className, onLinkClick, loadingLabel, errorLabel }) => {
|
|
9
|
+
const renderRef = useRef(null);
|
|
10
|
+
const [error, setError] = useState();
|
|
11
|
+
const [loading, setLoading] = useState(true);
|
|
12
|
+
const onLinkClickRef = useRef(onLinkClick);
|
|
13
|
+
onLinkClickRef.current = onLinkClick;
|
|
14
|
+
useRevokeBlobUrl(src);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const el = renderRef.current;
|
|
17
|
+
if (!src || !el) return;
|
|
18
|
+
let cancelled = false;
|
|
19
|
+
setLoading(true);
|
|
20
|
+
setError(void 0);
|
|
21
|
+
(async () => {
|
|
22
|
+
try {
|
|
23
|
+
const { resolveToArrayBuffer } = await import("./resolveToArrayBuffer-AQIDZHSQ.js");
|
|
24
|
+
const arrayBuf = await resolveToArrayBuffer(src);
|
|
25
|
+
if (cancelled || !el.isConnected) return;
|
|
26
|
+
const docxPreview = await import("docx-preview");
|
|
27
|
+
if (cancelled || !el.isConnected) return;
|
|
28
|
+
el.innerHTML = "";
|
|
29
|
+
await docxPreview.renderAsync(arrayBuf, el, void 0, {
|
|
30
|
+
className: "jr-word-docx",
|
|
31
|
+
inWrapper: true,
|
|
32
|
+
ignoreWidth: false,
|
|
33
|
+
ignoreHeight: false,
|
|
34
|
+
ignoreFonts: false,
|
|
35
|
+
breakPages: true,
|
|
36
|
+
trimXmlDeclaration: true,
|
|
37
|
+
useBase64URL: true
|
|
38
|
+
});
|
|
39
|
+
if (!cancelled) setLoading(false);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
if (!cancelled) {
|
|
42
|
+
setError(String(err?.message ?? err));
|
|
43
|
+
setLoading(false);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
})();
|
|
47
|
+
return () => {
|
|
48
|
+
cancelled = true;
|
|
49
|
+
if (el) el.innerHTML = "";
|
|
50
|
+
};
|
|
51
|
+
}, [src]);
|
|
52
|
+
const handleClick = useCallback((e) => {
|
|
53
|
+
const anchor = e.target.closest("a");
|
|
54
|
+
if (!anchor?.href) return;
|
|
55
|
+
e.preventDefault();
|
|
56
|
+
const href = anchor.getAttribute("href") ?? anchor.href;
|
|
57
|
+
if (onLinkClickRef.current) {
|
|
58
|
+
onLinkClickRef.current(href);
|
|
59
|
+
} else {
|
|
60
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
61
|
+
}
|
|
62
|
+
}, []);
|
|
63
|
+
if (error) {
|
|
64
|
+
return /* @__PURE__ */ jsx("div", { className: `ycw-word-viewer ${className || ""}`, children: /* @__PURE__ */ jsx("div", { className: "ycw-viewer-error", children: errorLabel || error }) });
|
|
65
|
+
}
|
|
66
|
+
return /* @__PURE__ */ jsxs("div", { className: `ycw-word-viewer ${className || ""}`, onClick: handleClick, children: [
|
|
67
|
+
loading && /* @__PURE__ */ jsx("div", { className: "ycw-viewer-loading", children: loadingLabel || "Loading\u2026" }),
|
|
68
|
+
/* @__PURE__ */ jsx("div", { ref: renderRef })
|
|
69
|
+
] });
|
|
70
|
+
};
|
|
71
|
+
var WordCore_default = WordCore;
|
|
72
|
+
|
|
73
|
+
export {
|
|
74
|
+
WordCore,
|
|
75
|
+
WordCore_default
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=chunk-K4KGNVL5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/ViewerCore/WordCore.tsx"],"sourcesContent":["import React, { useRef, useEffect, useState, useCallback } from 'react'\nimport { useRevokeBlobUrl } from './hooks/useRevokeBlobUrl.js'\n\nexport interface WordCoreProps {\n src?: string\n className?: string\n onLinkClick?: (url: string) => void\n loadingLabel?: string\n errorLabel?: string\n}\n\nexport const WordCore: React.FC<WordCoreProps> = ({ src, className, onLinkClick, loadingLabel, errorLabel }) => {\n const renderRef = useRef<HTMLDivElement>(null)\n const [error, setError] = useState<string>()\n const [loading, setLoading] = useState(true)\n const onLinkClickRef = useRef(onLinkClick)\n onLinkClickRef.current = onLinkClick\n useRevokeBlobUrl(src)\n\n useEffect(() => {\n const el = renderRef.current\n if (!src || !el) return\n\n let cancelled = false\n setLoading(true)\n setError(undefined)\n\n ;(async () => {\n try {\n const { resolveToArrayBuffer } = await import('./utils/resolveToArrayBuffer.js')\n const arrayBuf = await resolveToArrayBuffer(src)\n if (cancelled || !el.isConnected) return\n\n const docxPreview = await import('docx-preview')\n if (cancelled || !el.isConnected) return\n\n el.innerHTML = ''\n await docxPreview.renderAsync(arrayBuf, el, undefined, {\n className: 'jr-word-docx',\n inWrapper: true,\n ignoreWidth: false,\n ignoreHeight: false,\n ignoreFonts: false,\n breakPages: true,\n trimXmlDeclaration: true,\n useBase64URL: true,\n })\n if (!cancelled) setLoading(false)\n } catch (err) {\n if (!cancelled) {\n setError(String((err as Error)?.message ?? err))\n setLoading(false)\n }\n }\n })()\n\n return () => {\n cancelled = true\n // Safe cleanup: only clear the render target, not React-managed DOM\n if (el) el.innerHTML = ''\n }\n }, [src])\n\n const handleClick = useCallback((e: React.MouseEvent) => {\n const anchor = (e.target as HTMLElement).closest('a')\n if (!anchor?.href) return\n e.preventDefault()\n const href = anchor.getAttribute('href') ?? anchor.href\n if (onLinkClickRef.current) {\n onLinkClickRef.current(href)\n } else {\n window.open(href, '_blank', 'noopener,noreferrer')\n }\n }, [])\n\n if (error) {\n return <div className={`ycw-word-viewer ${className || ''}`}>\n <div className=\"ycw-viewer-error\">{errorLabel || error}</div>\n </div>\n }\n\n return (\n <div className={`ycw-word-viewer ${className || ''}`} onClick={handleClick}>\n {loading && <div className=\"ycw-viewer-loading\">{loadingLabel || 'Loading…'}</div>}\n <div ref={renderRef} />\n </div>\n )\n}\n\nexport default WordCore\n"],"mappings":";;;;;AAAA,SAAgB,QAAQ,WAAW,UAAU,mBAAmB;AA6E1D,cAKF,YALE;AAlEC,IAAM,WAAoC,CAAC,EAAE,KAAK,WAAW,aAAa,cAAc,WAAW,MAAM;AAC9G,QAAM,YAAY,OAAuB,IAAI;AAC7C,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAiB;AAC3C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,IAAI;AAC3C,QAAM,iBAAiB,OAAO,WAAW;AACzC,iBAAe,UAAU;AACzB,mBAAiB,GAAG;AAEpB,YAAU,MAAM;AACd,UAAM,KAAK,UAAU;AACrB,QAAI,CAAC,OAAO,CAAC,GAAI;AAEjB,QAAI,YAAY;AAChB,eAAW,IAAI;AACf,aAAS,MAAS;AAEjB,KAAC,YAAY;AACZ,UAAI;AACF,cAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,oCAAiC;AAC/E,cAAM,WAAW,MAAM,qBAAqB,GAAG;AAC/C,YAAI,aAAa,CAAC,GAAG,YAAa;AAElC,cAAM,cAAc,MAAM,OAAO,cAAc;AAC/C,YAAI,aAAa,CAAC,GAAG,YAAa;AAElC,WAAG,YAAY;AACf,cAAM,YAAY,YAAY,UAAU,IAAI,QAAW;AAAA,UACrD,WAAW;AAAA,UACX,WAAW;AAAA,UACX,aAAa;AAAA,UACb,cAAc;AAAA,UACd,aAAa;AAAA,UACb,YAAY;AAAA,UACZ,oBAAoB;AAAA,UACpB,cAAc;AAAA,QAChB,CAAC;AACD,YAAI,CAAC,UAAW,YAAW,KAAK;AAAA,MAClC,SAAS,KAAK;AACZ,YAAI,CAAC,WAAW;AACd,mBAAS,OAAQ,KAAe,WAAW,GAAG,CAAC;AAC/C,qBAAW,KAAK;AAAA,QAClB;AAAA,MACF;AAAA,IACF,GAAG;AAEH,WAAO,MAAM;AACX,kBAAY;AAEZ,UAAI,GAAI,IAAG,YAAY;AAAA,IACzB;AAAA,EACF,GAAG,CAAC,GAAG,CAAC;AAER,QAAM,cAAc,YAAY,CAAC,MAAwB;AACvD,UAAM,SAAU,EAAE,OAAuB,QAAQ,GAAG;AACpD,QAAI,CAAC,QAAQ,KAAM;AACnB,MAAE,eAAe;AACjB,UAAM,OAAO,OAAO,aAAa,MAAM,KAAK,OAAO;AACnD,QAAI,eAAe,SAAS;AAC1B,qBAAe,QAAQ,IAAI;AAAA,IAC7B,OAAO;AACL,aAAO,KAAK,MAAM,UAAU,qBAAqB;AAAA,IACnD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,MAAI,OAAO;AACT,WAAO,oBAAC,SAAI,WAAW,mBAAmB,aAAa,EAAE,IACvD,8BAAC,SAAI,WAAU,oBAAoB,wBAAc,OAAM,GACzD;AAAA,EACF;AAEA,SACE,qBAAC,SAAI,WAAW,mBAAmB,aAAa,EAAE,IAAI,SAAS,aAC5D;AAAA,eAAW,oBAAC,SAAI,WAAU,sBAAsB,0BAAgB,iBAAW;AAAA,IAC5E,oBAAC,SAAI,KAAK,WAAW;AAAA,KACvB;AAEJ;AAEA,IAAO,mBAAQ;","names":[]}
|