@nebula-spatial/viewer 0.1.0 → 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 +21 -0
- package/README.md +84 -29
- package/dist/assets/geo-prepare.worker-ClQZBxyx.js +1 -0
- package/dist/cad/types.d.ts +258 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15516 -283
- package/dist/types.d.ts +80 -14
- package/package.json +8 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this package are documented in this file.
|
|
4
|
+
|
|
5
|
+
## 0.2.1
|
|
6
|
+
|
|
7
|
+
- Resolved the geometry preparation Worker from the published package instead of the site root.
|
|
8
|
+
- Added `CadOpenOptions.workerUrl` and `workerFactory` for custom Worker hosting.
|
|
9
|
+
- Use the built-in room environment by default and support external HDR URLs through `ViewerOptions.environment`.
|
|
10
|
+
|
|
11
|
+
## 0.2.0
|
|
12
|
+
|
|
13
|
+
- Added `viewer.cad` for opening, closing, and observing CAD documents.
|
|
14
|
+
- Added CAD document, layer, block, inspector, HUD, camera state, and optional read-only UI models.
|
|
15
|
+
- Added pointer, viewport, interaction, content, and camera lifecycle events.
|
|
16
|
+
- Added the runtime dependency on `@nebula-spatial/cad-loader` for CAD document support.
|
|
17
|
+
- Retained the existing generic Three.js object management and picking APIs.
|
|
18
|
+
|
|
19
|
+
## 0.1.0
|
|
20
|
+
|
|
21
|
+
- Initial public release of the read-only Three.js Viewer facade.
|
package/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# @nebula-spatial/viewer
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
`
|
|
5
|
-
|
|
3
|
+
浏览器侧只读 Three.js Viewer Facade。负责场景运行时、相机、输入、拾取、渲染循环和
|
|
4
|
+
资源释放;`viewer.cad` 提供与 `@nebula-spatial/cad-loader` 集成的 CAD 文档能力。
|
|
5
|
+
|
|
6
|
+
Viewer 不解析 DXF/DWG,也不提供编辑命令、历史记录或业务状态管理。
|
|
7
|
+
|
|
8
|
+
## CAD 快速开始
|
|
6
9
|
|
|
7
10
|
```ts
|
|
8
11
|
import { createViewer } from '@nebula-spatial/viewer';
|
|
@@ -10,37 +13,89 @@ import { createViewer } from '@nebula-spatial/viewer';
|
|
|
10
13
|
const viewer = createViewer({
|
|
11
14
|
viewport: document.querySelector<HTMLElement>('#viewport')!,
|
|
12
15
|
canvas: document.querySelector<HTMLCanvasElement>('#viewport canvas')!,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
initialViewMode: '2d',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
viewer.cad.on('document-change', ({ document }) => {
|
|
20
|
+
updateDocumentTitle(document?.filename ?? '');
|
|
17
21
|
});
|
|
18
22
|
|
|
19
|
-
viewer.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
await viewer.cad.open('/api/files/demo/result', {
|
|
24
|
+
documentKey: 'demo',
|
|
25
|
+
filename: 'demo.dxf',
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
viewer.dispose();
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Viewer 默认使用 Three.js 内置 `RoomEnvironment` 提供基于图像的环境光,不会替换场景背景。
|
|
32
|
+
外部系统也可以传入自己的等距柱状 HDR URL:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const viewer = createViewer({
|
|
36
|
+
viewport,
|
|
37
|
+
canvas,
|
|
38
|
+
environment: {
|
|
39
|
+
type: 'hdr',
|
|
40
|
+
url: 'https://static.example.com/environments/studio.hdr',
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
HDR 资源由浏览器直接请求,因此资源服务器需要允许当前应用域名进行 CORS 访问。Viewer
|
|
46
|
+
销毁时会释放已经加载的环境纹理;加载失败时保留原场景背景并在控制台输出警告。
|
|
47
|
+
|
|
48
|
+
几何准备 Worker 默认从 Viewer npm 包内的相对资源路径加载,支持应用部署在子路径。
|
|
49
|
+
需要自行托管 Worker 或满足特定 CSP 时,可通过 `CadOpenOptions.workerUrl` 或
|
|
50
|
+
`workerFactory` 覆盖 Worker 创建方式。
|
|
51
|
+
|
|
52
|
+
`CadLoadSource` 支持 URL、`ArrayBuffer`、`File` 及对应的 `{ kind: ... }` 形式。`open()`
|
|
53
|
+
会替换当前 CAD 文档;调用 `viewer.cad.close()` 可仅关闭文档并保留 Viewer。
|
|
54
|
+
|
|
55
|
+
`viewer.cad` 暴露以下只读模型,可通过 `document-change`、`layer-change`、
|
|
56
|
+
`block-change`、`inspector-change` 和 `hud-change` 绑定到产品 UI:
|
|
57
|
+
|
|
58
|
+
- `document`:文档信息和加载阶段。
|
|
59
|
+
- `layers`:图层可见性与颜色覆盖。
|
|
60
|
+
- `blocks`:INSERT 使用项和实例可见性。
|
|
61
|
+
- `inspector`:当前 CAD INSERT 或文本选择。
|
|
62
|
+
- `hud`:视图与渲染统计。
|
|
63
|
+
|
|
64
|
+
可选的 `ui` 配置会挂载 `cad-readonly` 预设 UI;产品层也可以完全自行呈现这些模型。
|
|
65
|
+
|
|
66
|
+
## 通用 Three.js 对象
|
|
67
|
+
|
|
68
|
+
Viewer 同样可管理非 CAD 的 `Object3D`:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
viewer.addObject(model);
|
|
72
|
+
viewer.fitView(model);
|
|
23
73
|
|
|
24
74
|
const stopPicking = viewer.on('pick', ({ result }) => {
|
|
25
|
-
|
|
75
|
+
selectObject(result?.object ?? null);
|
|
26
76
|
});
|
|
27
77
|
|
|
28
|
-
|
|
78
|
+
viewer.setHighlight(model, { color: 0x5b8cff });
|
|
79
|
+
stopPicking();
|
|
29
80
|
```
|
|
30
81
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
82
|
+
默认点击会执行通用 Raycaster 拾取。格式专用的交互可通过 `pointerPick: false` 关闭它,
|
|
83
|
+
并监听 `pointer-click`、`pointer-move` 和 `pointer-leave`。`screenToWorldOnPlane()` 用于
|
|
84
|
+
通用的屏幕坐标到世界平面转换。
|
|
85
|
+
|
|
86
|
+
## 生命周期
|
|
87
|
+
|
|
88
|
+
Viewer 借用 `addObject()` 传入的 `Object3D`。`removeObject()` 和 `dispose()` 只解除场景
|
|
89
|
+
挂载,不会释放调用方的 Geometry、Material 或 Texture。
|
|
90
|
+
|
|
91
|
+
Viewer 自行拥有 SceneRuntime、Renderer、Camera、Controls、事件监听和 CAD 会话;调用
|
|
92
|
+
`dispose()` 会统一释放这些资源。运行时依赖为 `three` peer dependency,要求 Node.js 18
|
|
93
|
+
或更高版本。
|
|
94
|
+
|
|
95
|
+
## 开发
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npm run typecheck --workspace @nebula-spatial/viewer
|
|
99
|
+
npm test --workspace @nebula-spatial/viewer
|
|
100
|
+
npm run build --workspace @nebula-spatial/viewer
|
|
101
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var Fr=Object.defineProperty;var Te=u=>{throw TypeError(u)};var Xr=(u,C,O)=>C in u?Fr(u,C,{enumerable:!0,configurable:!0,writable:!0,value:O}):u[C]=O;var et=(u,C,O)=>Xr(u,typeof C!="symbol"?C+"":C,O),Yr=(u,C,O)=>C.has(u)||Te("Cannot "+O);var st=(u,C,O)=>(Yr(u,C,"read from private field"),O?O.call(u):C.get(u)),Be=(u,C,O)=>C.has(u)?Te("Cannot add the same private member more than once"):C instanceof WeakSet?C.add(u):C.set(u,O);(function(){"use strict";var j;class u extends Error{constructor(n,r){super(r);et(this,"code");this.name="GeoLoaderError",this.code=n}}const C=4096;function O(t){return t>=6?"u16_lw":t>=5?"u8_lw":t>=4?"u16":"u8"}function Dt(t){return t==="u16_lw"?13:t==="u8_lw"?12:t==="u16"?9:8}function kt(t,e,n){return n==="u16"||n==="u16_lw"?t.getUint16(e+7,!0):t.getUint8(e+7)}function $e(t){return t==="u16"||t==="u16_lw"?2:1}function Lt(t,e,n){if(!(n!=="u8_lw"&&n!=="u16_lw"))return t.getFloat32(e+7+$e(n),!0)}function Ft(t,e,n,r,o=t.byteLength,s="u8"){if(n>o||o>t.byteLength)throw new u("E_GROUP_RANGE","Group byte range exceeds payload length");let i=n;const a=r*2,c=a*4;if(i+c>o)throw new u("E_GROUP_RANGE","Group position bytes exceed payload length");let l;if(a>0){const w=new Uint8Array(t,i,c),y=new Uint8Array(c),f=a;for(let _=0;_<a;_++)y[_*4]=w[_],y[_*4+1]=w[f+_],y[_*4+2]=w[f*2+_],y[_*4+3]=w[f*3+_];l=new Float32Array(y.buffer)}else l=new Float32Array(0);if(i+=c,i+4>o)throw new u("E_GROUP_RANGE","Missing seg_count field for group");const m=e.getUint32(i,!0);i+=4;const g=[];let d=0;const h=Dt(s);for(let w=0;w<m;w++){if(i+h>o)throw new u("E_GROUP_RANGE","Segment record exceeds payload length");const y=e.getUint32(i,!0),f=e.getUint8(i+4),_=e.getUint8(i+5),b=e.getUint8(i+6),E=kt(e,i,s),p=Lt(e,i,s);if(d+y>r)throw new u("E_SEGMENT_SUM","Segment vertex_count sum exceeds group count");g.push({startVertex:d,vertexCount:y,color:[f,_,b],layerIndex:E,...p===void 0?{}:{lineweightPx:p}}),i+=h;const T=d*2;if(y>1){let N=l[T],P=l[T+1];for(let G=1;G<y;G++){const U=T+G*2;N+=l[U],P+=l[U+1],l[U]=N,l[U+1]=P}}d+=y}if(d!==r)throw new u("E_SEGMENT_SUM",`Segment vertex_count sum ${d} does not match group count ${r}`);return{chunk:{pos:l,count:r,segments:g},offset:i}}function Oe(t,e,n,r,o="u8"){const s=r*2,i=s*4;if(n+i>t.byteLength)throw new u("E_GROUP_RANGE","Group position bytes exceed payload length");const a=new Uint8Array(t,n,i);let c=n+i;if(c+4>t.byteLength)throw new u("E_GROUP_RANGE","Missing seg_count field for group");const l=e.getUint32(c,!0);c+=4;const m=[];let g=0;const d=Dt(o);for(let h=0;h<l;h++){if(c+d>t.byteLength)throw new u("E_GROUP_RANGE","Segment record exceeds payload length");const w=e.getUint32(c,!0),y=e.getUint8(c+4),f=e.getUint8(c+5),_=e.getUint8(c+6),b=kt(e,c,o),E=Lt(e,c,o);if(c+=d,g+w>r)throw new u("E_SEGMENT_SUM","Segment vertex_count sum exceeds group count");m.push({startVertex:g,vertexCount:w,color:[y,f,_],layerIndex:b,...E===void 0?{}:{lineweightPx:E}}),g+=w}if(g!==r)throw new u("E_SEGMENT_SUM",`Segment vertex_count sum ${g} does not match group count ${r}`);return{shuffled:a,plane:s,segments:m,offset:c}}function ve(t,e,n,r){if(r===0)return new Float32Array(0);const o=new Uint8Array(r*4);for(let s=0;s<r;s++)o[s*4]=t[n+s],o[s*4+1]=t[e+n+s],o[s*4+2]=t[e*2+n+s],o[s*4+3]=t[e*3+n+s];return new Float32Array(o.buffer)}function Me(t,e,n,r,o){const s=ve(t.shuffled,t.plane,(e.startVertex+n)*2,r*2);let i=(o==null?void 0:o[0])??0,a=(o==null?void 0:o[1])??0;if(r>0){n===0?(i=s[0],a=s[1]):(i+=s[0],a+=s[1],s[0]=i,s[1]=a);for(let l=1;l<r;l++){const m=l*2;i+=s[m],a+=s[m+1],s[m]=i,s[m+1]=a}}const c=r>0?[{startVertex:0,vertexCount:r,color:[e.color[0],e.color[1],e.color[2]],layerIndex:e.layerIndex,...e.lineweightPx===void 0?{}:{lineweightPx:e.lineweightPx}}]:[];return{chunk:{pos:s,count:r,segments:c},lastPoint:r>0?[i,a]:o}}function*De(t,e,n,r,o="u8"){const s=Oe(t,e,n,r,o);if(r===0)return yield{pos:new Float32Array(0),count:0,segments:[]},s.offset;for(const i of s.segments){let a=null;for(let c=0;c<i.vertexCount;c+=C){const l=Math.min(C,i.vertexCount-c),m=Me(s,i,c,l,a);a=m.lastPoint,yield m.chunk}}return s.offset}function Xt(){const t=globalThis.TextDecoder;if(!t)throw new u("E_HEADER_JSON","TextDecoder is required to parse CAD pack metadata");return new t}function it(t){return t?{minX:t.minX,minY:t.minY,maxX:t.maxX,maxY:t.maxY}:null}function xt(t){return!!t&&Number.isFinite(t.minX)&&Number.isFinite(t.minY)&&Number.isFinite(t.maxX)&&Number.isFinite(t.maxY)}function ct(t){return xt(t)?it(t):null}function Yt(t,e){const n=xt(t)?t:null,r=xt(e)?e:null;return n?r?{minX:Math.min(n.minX,r.minX),minY:Math.min(n.minY,r.minY),maxX:Math.max(n.maxX,r.maxX),maxY:Math.max(n.maxY,r.maxY)}:it(n):it(r)}function ke(t,e,n,r=0,o=1){if(e<=0||n<=0)return null;let s=Number.POSITIVE_INFINITY,i=Number.POSITIVE_INFINITY,a=Number.NEGATIVE_INFINITY,c=Number.NEGATIVE_INFINITY,l=!1;for(let m=0;m<e;m+=1){const g=m*n,d=t[g+r],h=t[g+o];!Number.isFinite(d)||!Number.isFinite(h)||(d<s&&(s=d),h<i&&(i=h),d>a&&(a=d),h>c&&(c=h),l=!0)}return l?{minX:s,minY:i,maxX:a,maxY:c}:null}function zt(t,e){const n=t.minX,r=t.minY,o=t.maxX,s=t.maxY,{matA:i,matB:a,matC:c,matD:l,tx:m,ty:g}=e;let d=i*n+c*r+m,h=a*n+l*r+g,w=d,y=h,f=d,_=h;return d=i*n+c*s+m,h=a*n+l*s+g,d<w&&(w=d),h<y&&(y=h),d>f&&(f=d),h>_&&(_=h),d=i*o+c*r+m,h=a*o+l*r+g,d<w&&(w=d),h<y&&(y=h),d>f&&(f=d),h>_&&(_=h),d=i*o+c*s+m,h=a*o+l*s+g,d<w&&(w=d),h<y&&(y=h),d>f&&(f=d),h>_&&(_=h),{minX:w,minY:y,maxX:f,maxY:_}}function Le(t){return Math.hypot(t.maxX-t.minX,t.maxY-t.minY)}function Fe(t,e){const n=(t.minX+t.maxX)/2,r=(t.minY+t.maxY)/2,o=(e.minX+e.maxX)/2,s=(e.minY+e.maxY)/2;return Math.hypot(n-o,r-s)}const Xe={};function Ht(t){return typeof t=="object"&&t!==null}function ut(t,e){return Object.prototype.hasOwnProperty.call(t,e)}function K(t){if(t.length===0)return"$";let e="";for(const n of t){if(typeof n=="number"){e+=`[${n}]`;continue}e+=e.length===0?n:`.${n}`}return e}function Kt(t,e,n,r){return new u("E_TEXT_ROUNDTRIP",`Text roundtrip mismatch at stage=${t} index=${e} path=${n}: ${r}`)}function _t(t,e,n){if(Object.is(t,e))return null;if(Array.isArray(t)){if(!Array.isArray(e))return{path:K(n),reason:`expected array but found ${typeof e}`};if(t.length!==e.length)return{path:K([...n,"length"]),reason:`array length ${t.length} !== ${e.length}`};for(let r=0;r<t.length;r+=1){const o=_t(t[r],e[r],[...n,r]);if(o)return o}return null}if(Ht(t)){if(!Ht(e)||Array.isArray(e))return{path:K(n),reason:`expected object but found ${Array.isArray(e)?"array":typeof e}`};const r=Object.keys(t),o=Object.keys(e);if(r.length!==o.length){const s=r.find(a=>!ut(e,a));if(s!==void 0)return{path:K([...n,s]),reason:"missing key on actual"};const i=o.find(a=>!ut(t,a));if(i!==void 0)return{path:K([...n,i]),reason:"extra key on actual"}}for(const s of r){if(!ut(e,s))return{path:K([...n,s]),reason:"missing key on actual"};const i=_t(t[s],e[s],[...n,s]);if(i)return i}for(const s of o)if(!ut(t,s))return{path:K([...n,s]),reason:"extra key on actual"};return null}return{path:K(n),reason:`expected ${String(t)} but found ${String(e)}`}}function Ye(t,e){return _t(t,e,[])}function jt(t){if(t===!0||t==="1"||t==="true")return!0;if(t===!1||t==="0"||t==="false")return!1}function ze(){var o,s;const t=globalThis.process,e=jt(((o=t==null?void 0:t.env)==null?void 0:o.DXF_STRICT_TEXT_ROUNDTRIP)??((s=t==null?void 0:t.env)==null?void 0:s.VITE_DXF_STRICT_TEXT_ROUNDTRIP));if(e!==void 0)return e;const n=Xe,r=jt(n==null?void 0:n.VITE_DXF_STRICT_TEXT_ROUNDTRIP);return r!==void 0?r:!1}function He(t,e,n){if(e.length!==n.length)throw Kt(t,Math.min(e.length,n.length),"$length",`text count ${e.length} !== ${n.length}`);for(let r=0;r<e.length;r+=1){const o=Ye(e[r],n[r]);if(o)throw Kt(t,r,o.path,o.reason)}}Xt();function Wt(t,e){if(t>BigInt(Number.MAX_SAFE_INTEGER))throw new u("E_GROUP_RANGE",`${e} exceeds safe integer range`);return Number(t)}function qt(t,e,n,r){if(!Number.isInteger(t)||!Number.isInteger(e)||t<0||e<0||t+e>n)throw new u("E_GROUP_RANGE",`${r} exceeds payload length`)}function Ke(t){if(t.byteLength<4)return!1;const e=new Uint8Array(t,0,4);return e[0]===68&&e[1]===88&&e[2]===66&&e[3]===83}function je(t){if(t.byteLength<20)throw new u("E_HEADER","DXBS payload too small: missing container header");if(!Ke(t))throw new u("E_HEADER","DXBS payload missing magic");const e=new DataView(t),n=e.getUint16(4,!0),r=e.getUint16(6,!0),o=e.getUint16(8,!0),s=e.getUint16(10,!0),i=e.getUint16(12,!0),a=e.getUint16(14,!0),c=e.getUint32(16,!0);if(n!==3||r<3||r>6)throw new u("E_GROUP_RANGE",`Unsupported DXBS version: ${n}.${r}`);if(o!==0)throw new u("E_GROUP_RANGE",`Unsupported DXBS sidecar kind: ${o}`);if(a!==0)throw new u("E_GROUP_RANGE",`Invalid DXBS reserved field: ${a}`);if(s<24)throw new u("E_GROUP_RANGE",`Invalid DXBS directory entry size: ${s}`);if(c!==s*i)throw new u("E_GROUP_RANGE","DXBS directory byte size mismatch");const l=20;qt(l,c,t.byteLength,"DXBS section directory");const m=new Map;for(let g=0;g<i;g+=1){const d=l+g*s,h=e.getUint16(d,!0),w=e.getUint16(d+2,!0),y=e.getUint32(d+4,!0),f=Wt(e.getBigUint64(d+8,!0),"DXBS section offset"),_=Wt(e.getBigUint64(d+16,!0),"DXBS section length");if(w!==0)throw new u("E_GROUP_RANGE",`Unsupported DXBS section flags for type ${h}: ${w}`);if(y!==0)throw new u("E_GROUP_RANGE",`Invalid DXBS section reserved field for type ${h}: ${y}`);qt(f,_,t.byteLength,`DXBS section ${h}`),m.set(h,{type:h,flags:w,offset:f,length:_})}return{versionMajor:n,versionMinor:r,sections:m}}function We(t,e,n){const r=t.sections.get(e);if(!r)throw new u("E_GROUP_RANGE",`Missing DXBS section ${n}`);return r}function qe(){return{pos:new Float32Array(0),count:0,segments:[]}}function Et(t){if(t.segments&&t.segments.length>0)return Ze(t.segments,t.count),t.segments;if(t.count<=0)return[];if(!t.col||!t.lay)throw new u("E_GROUP_RANGE","Geometry chunk is missing segment or expanded color/layer metadata");return Je(t.col,t.lay,t.count)}function Jt(t){const e=[];for(const n of t){const r=e[e.length-1];if(r&&r.startVertex+r.vertexCount===n.startVertex&&r.layerIndex===n.layerIndex&&r.color[0]===n.color[0]&&r.color[1]===n.color[1]&&r.color[2]===n.color[2]&&r.lineweightPx===n.lineweightPx){e[e.length-1]={...r,vertexCount:r.vertexCount+n.vertexCount};continue}e.push({startVertex:n.startVertex,vertexCount:n.vertexCount,color:Qe(n),layerIndex:n.layerIndex,...n.lineweightPx===void 0?{}:{lineweightPx:n.lineweightPx}})}return e}function Je(t,e,n){if(t.length<n*3||e.length<n)throw new u("E_GROUP_RANGE","Expanded color/layer metadata is shorter than geometry count");const r=[];let o=0;for(;o<n;){const s=o*3,i=t[s]??0,a=t[s+1]??0,c=t[s+2]??0,l=e[o]??0;let m=o+1;for(;m<n;){const g=m*3;if(e[m]!==l||t[g]!==i||t[g+1]!==a||t[g+2]!==c)break;m+=1}r.push({startVertex:o,vertexCount:m-o,color:[i,a,c],layerIndex:l}),o=m}return r}function Ze(t,e){let n=0;for(const r of t){if(r.vertexCount<0||r.startVertex!==n)throw new u("E_SEGMENT_SUM","Geometry segments must be contiguous and non-negative");n+=r.vertexCount}if(n!==e)throw new u("E_SEGMENT_SUM",`Geometry segment vertex sum ${n} does not match count ${e}`)}function Qe(t){return[t.color[0],t.color[1],t.color[2]]}const tn=8e6,wt=Xt(),en=["left","center","right"],nn=["top","middle","bottom","alphabetic"];function Zt(t,e,n){for(const r of t)n(r);for(const r of e)n(r)}function nt(t){return typeof t=="object"&&t!==null}function rn(t){return Array.isArray(t)?"array":t===null?"null":typeof t}function on(t){return!(!nt(t)||Array.isArray(t)||typeof t.t!="string"||typeof t.x!="number"||typeof t.y!="number"||typeof t.h!="number"||typeof t.r!="number"||!Array.isArray(t.c)||t.c.length!==3||!t.c.every(e=>typeof e=="number")||typeof t.li!="number"||t.ha!=="left"&&t.ha!=="center"&&t.ha!=="right"||t.va!=="top"&&t.va!=="middle"&&t.va!=="bottom"&&t.va!=="alphabetic"||typeof t.lh!="number"||t.w!==void 0&&typeof t.w!="number"||t.wf!==void 0&&typeof t.wf!="number"||t.iv!==void 0&&typeof t.iv!="number"||t.io!==void 0&&typeof t.io!="number"||t.mx!==void 0&&t.mx!==!0||t.my!==void 0&&t.my!==!0)}function sn(t){return t.map((e,n)=>({index:n,name:e.name,color:[...e.color],lw_px:e.lw_px,visible:e.visible??!0}))}function Qt(t){const e=t.texts,n=Array.isArray(e)?e:[],r=n.filter(on),o=ze();if(o&&e!==void 0&&!Array.isArray(e))throw new u("E_TEXT_ROUNDTRIP",`Text roundtrip mismatch at stage=Boundary-2:header->stream index=0 path=$: expected array but found ${rn(e)}`);return o&&He("Boundary-2:header->stream",n,r),{bounds:[...t.bounds],entityCount:Number(t.entity_count||0),lineCount:Number(t.line_count||0),fillCount:Number(t.fill_count||0),dotCount:Number(t.dot_count||0),textCount:r.length,layers:sn(t.layers??[]),texts:r}}function an(t){const e=t==null?void 0:t.maxExpandedInstanceVertices,n=typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.floor(e):tn;return{hiddenInstanceIds:t!=null&&t.hiddenInstanceIds?new Set(t.hiddenInstanceIds):new Set,keepTextsForHiddenInstances:(t==null?void 0:t.keepTextsForHiddenInstances)===!0,loadBlocks:(t==null?void 0:t.loadBlocks)!==!1,suppressExpandedInsertGeometry:(t==null?void 0:t.suppressExpandedInsertGeometry)===!0,maxExpandedInstanceVertices:n,expandedInstanceVertices:0,externalVariantBuffers:t==null?void 0:t.externalVariantBuffers,requiredExternalVariantIds:t==null?void 0:t.requiredExternalVariantIds,externalVariantDeltaOnly:(t==null?void 0:t.externalVariantDeltaOnly)===!0,deferExternalVariantGeometry:(t==null?void 0:t.deferExternalVariantGeometry)===!0}}function cn(t){return t.loadBlocks&&!t.suppressExpandedInsertGeometry}function te(t,e){return cn(e)&&!e.hiddenInstanceIds.has(t)}function un(t,e,n){if(n<=0)return;const r=t.expandedInstanceVertices+n;if(r>t.maxExpandedInstanceVertices)throw new u("E_EXPANSION_BUDGET",`CPU-expanded ${e} instance vertices exceed budget: ${r}/${t.maxExpandedInstanceVertices}. Disable block loading or raise maxExpandedInstanceVertices.`);t.expandedInstanceVertices=r}function ln(t,e,n){return n.loadBlocks?n.hiddenInstanceIds.size===0||n.keepTextsForHiddenInstances?t:t.filter(r=>{if(!Number.isInteger(r.iv)||!Number.isInteger(r.io))return!0;const o=e.get(`${r.iv}:${r.io}`);return o===void 0||!n.hiddenInstanceIds.has(o)}):t.filter(r=>!Number.isInteger(r.iv)||!Number.isInteger(r.io))}function fn(t,e){const n=new Map;return t.forEach((r,o)=>{if(!Number.isInteger(r.iv)||!Number.isInteger(r.io))return;const s=e.get(`${r.iv}:${r.io}`);if(s===void 0)return;const i=n.get(s);i?i.push(o):n.set(s,[o])}),n}function dn(t,e,n,r,o,s,i){const a=e.map((c,l)=>({id:c.id,blockName:ee(c,l),line:n[l].line,fill:n[l].fill,dot:n[l].dot,texts:r.get(c.id)??[]}));return{layer0Index:t,variants:a,instances:o,textIndexesByInstanceId:fn(s,i),ownerInstanceIdByVariantOrdinal:i}}function mn(t){if(t.byteLength<4)throw new u("E_HEADER","Payload too small: missing header length");const e=new DataView(t),n=e.getUint32(0,!0),r=4,o=r+n;if(o>t.byteLength)throw new u("E_HEADER","Header length exceeds payload length");let s;try{s=JSON.parse(wt.decode(new Uint8Array(t,r,n)))}catch(i){throw new u("E_HEADER_JSON",`Invalid JSON header: ${i.message}`)}return{meta:s,header:Qt(s),dataOffset:o,view:e}}function ee(t,e){var s,i,a;const n=(s=t.name)==null?void 0:s.trim();if(n)return n;const r=(i=t.block_name)==null?void 0:i.trim();if(r)return r;const o=(a=t.blockName)==null?void 0:a.trim();return o||`block_${e}`}function hn(t){const e=Number(t.version??1),n=String(t.encoding??"").toLowerCase();if(e===2){const r=n?` ${n}`:"";throw new u("E_UNSUPPORTED_PACK_VERSION",`当前文件是 V2${r} pack,前端不再兼容解析;请升级到最新版本后再打开。`)}}function gn(t){const e=mn(t);return hn(e.meta),e}function yn(t){if(t.byteLength<4)return!1;const e=new Uint8Array(t,0,4);return e[0]===68&&e[1]===88&&e[2]===66&&e[3]===51}function ne(t,e){if(t>BigInt(Number.MAX_SAFE_INTEGER))throw new u("E_GROUP_RANGE",`${e} exceeds safe integer range`);return Number(t)}function at(t,e,n,r){if(!Number.isInteger(t)||!Number.isInteger(e)||t<0||e<0||t+e>n)throw new u("E_GROUP_RANGE",`${r} exceeds payload length`)}function xn(t){if(t.byteLength<20)throw new u("E_HEADER","V3 payload too small: missing container header");const e=new DataView(t),n=e.getUint16(4,!0),r=e.getUint16(6,!0),o=e.getUint32(8,!0),s=e.getUint16(12,!0),i=e.getUint16(14,!0),a=e.getUint32(16,!0);if(n!==3||r>6)throw new u("E_GROUP_RANGE",`Unsupported V3 version: ${n}.${r}`);if(o!==0)throw new u("E_GROUP_RANGE",`Unsupported V3 file flags: ${o}`);if(s<24)throw new u("E_GROUP_RANGE",`Invalid V3 directory entry size: ${s}`);if(a!==s*i)throw new u("E_GROUP_RANGE","V3 directory byte size mismatch");const c=20;at(c,a,t.byteLength,"V3 section directory");const l=new Map;for(let m=0;m<i;m+=1){const g=c+m*s,d=e.getUint16(g,!0),h=e.getUint16(g+2,!0),w=e.getUint32(g+4,!0),y=ne(e.getBigUint64(g+8,!0),"V3 section offset"),f=ne(e.getBigUint64(g+16,!0),"V3 section length");if(h!==0)throw new u("E_GROUP_RANGE",`Unsupported V3 section flags for type ${d}: ${h}`);if(w!==0)throw new u("E_GROUP_RANGE",`Invalid V3 section reserved field for type ${d}: ${w}`);at(y,f,t.byteLength,`V3 section ${d}`),l.set(d,{type:d,flags:h,offset:y,length:f})}return{versionMinor:r,sections:l}}function q(t,e,n){const r=t.get(e);if(!r)throw new u("E_GROUP_RANGE",`Missing V3 section ${n}`);return r}function pt(t,e){return t.get(e)??{type:e,flags:0,offset:0,length:0}}function _n(t,e,n){try{return JSON.parse(wt.decode(new Uint8Array(t,e.offset,e.length)))}catch(r){throw new u("E_HEADER_JSON",`Invalid V3 ${n} JSON: ${r.message}`)}}function En(t){const e=String(t.encoding??"").toLowerCase();return e==="nested_instanced_external"||e==="nested_instanced_external_annotations"}function wn(t){return String(t.encoding??"").toLowerCase()==="nested_instanced_external_annotations"}function pn(t,e,n){const r=t.features,o=r&&typeof r=="object"&&!Array.isArray(r)?{...r}:{};return e&&(o.has_external_variant_geometry=!0),n&&(o.has_external_annotations=!0),Object.keys(o).length?o:void 0}function k(t,e){if(!Number.isInteger(t)||Number(t)<0)throw new u("E_HEADER",`${e} must be a non-negative integer`);return Number(t)}function re(t,e){if(typeof t!="string"||!t.trim())throw new u("E_HEADER",`${e} must be a non-empty string`);return t}function oe(t,e){if(t==null)return null;if(!Array.isArray(t)||t.length!==4||t.some(n=>typeof n!="number"||!Number.isFinite(n)))throw new u("E_HEADER",`${e} must be null or [minX, minY, maxX, maxY]`);return[t[0],t[1],t[2],t[3]]}function bt(t,e){if(!nt(t)||Array.isArray(t))throw new u("E_HEADER",`${e} must be an object`);return{line_count:k(t.line_count,`${e}.line_count`),fill_count:k(t.fill_count,`${e}.fill_count`),dot_count:k(t.dot_count,`${e}.dot_count`),bbox:oe(t.bbox,`${e}.bbox`),own_bbox:oe(t.own_bbox,`${e}.own_bbox`)}}function bn(t){return t?{minX:t[0],minY:t[1],maxX:t[2],maxY:t[3]}:null}function An(t,e){const n=t.external_variants;if(!Array.isArray(n))throw new u("E_HEADER","V3 external SCENE_META.external_variants must be an array");if(n.length!==e)throw new u("E_GROUP_RANGE",`V3 external variant manifest count mismatch: manifest=${n.length}, table=${e}`);return n.map((r,o)=>{if(!nt(r)||Array.isArray(r))throw new u("E_HEADER",`V3 external_variants[${o}] must be an object`);const s=k(r.id,`V3 external_variants[${o}].id`);if(s!==o)throw new u("E_GROUP_RANGE",`V3 external_variants[${o}].id must equal ${o}, found ${s}`);const i=re(r.href,`V3 external_variants[${o}].href`),a=k(r.raw_size,`V3 external_variants[${o}].raw_size`);if("normal"in r||"annotation"in r){const c=bt(r.annotation,`V3 external_variants[${o}].annotation`);return{id:s,href:i,raw_size:a,normal:bt(r.normal,`V3 external_variants[${o}].normal`),annotation:{...c,text_count:k(nt(r.annotation)&&!Array.isArray(r.annotation)?r.annotation.text_count:void 0,`V3 external_variants[${o}].annotation.text_count`)}}}return{id:s,href:i,raw_size:a,line_count:k(r.line_count,`V3 external_variants[${o}].line_count`),fill_count:k(r.fill_count,`V3 external_variants[${o}].fill_count`),dot_count:k(r.dot_count,`V3 external_variants[${o}].dot_count`)}})}function In(t){const e=t.external_annotations;if(e==null)return null;if(!nt(e)||Array.isArray(e))throw new u("E_HEADER","V3 external_annotations must be an object");const n=e.scene;if(n==null)return{};if(!nt(n)||Array.isArray(n))throw new u("E_HEADER","V3 external_annotations.scene must be an object");const r=bt(n,"V3 external_annotations.scene");return{scene:{href:re(n.href,"V3 external_annotations.scene.href"),raw_size:k(n.raw_size,"V3 external_annotations.scene.raw_size"),...r,text_count:k(n.text_count,"V3 external_annotations.scene.text_count")}}}function lt(t,e,n,r){return at(e,n,t.byteLength,r),wt.decode(t.subarray(e,e+n))}function Rn(t,e,n){if(e.length%20!==0)throw new u("E_GROUP_RANGE","V3 LAYER_TABLE length must be a multiple of 20");const r=new DataView(t),o=[];for(let s=e.offset;s<e.offset+e.length;s+=20){const i=r.getUint32(s,!0),a=r.getUint32(s+4,!0);o.push({name:lt(n,i,a,"V3 layer name"),color:[r.getUint8(s+8),r.getUint8(s+9),r.getUint8(s+10)],visible:r.getUint8(s+11)!==0,lw_px:r.getFloat32(s+12,!0)})}return o}function ft(t,e,n,r,o,s){if(n+4>r)throw new u("E_GROUP_RANGE",`Missing ${o} vertex_count`);const i=e.getUint32(n,!0),a=n+4,c=Ft(t,e,a,i,r,s);if(c.offset>r)throw new u("E_GROUP_RANGE",`${o} exceeds section bounds`);return{chunk:c.chunk,offset:c.offset}}function se(t,e,n,r,o,s){const i=ft(t,e,n,r,o,s),a=n+4;return{chunk:i.chunk,snapshot:{count:i.chunk.count,raw:new Uint8Array(t,a,i.offset-a).slice(),groupLayerEncoding:s},offset:i.offset}}function dt(t="u8"){return{chunk:{pos:new Float32Array(0),col:new Uint8Array(0),lay:new Uint8Array(0),count:0},snapshot:{count:0,raw:new Uint8Array(0),groupLayerEncoding:t}}}function Vn(t="u8"){return{line:dt(t),fill:dt(t),dot:dt(t)}}function Nn(t,e,n){var r;return!!(e&&n&&t.deferExternalVariantGeometry&&!((r=t.externalVariantBuffers)!=null&&r.has(e.id)))}function At(t,e,n,r,o,s,i){if(o===0)return dt(i);at(r,o,n.length,s);const a=n.offset+r,c=a+o,l=se(t,e,a,c,s,i);if(l.offset!==c)throw new u("E_GROUP_RANGE",`${s} has trailing bytes`);return{chunk:l.chunk,snapshot:l.snapshot}}function ie(t,e,n){if([t.getUint32(e+8,!0),t.getUint32(e+12,!0),t.getUint32(e+16,!0),t.getUint32(e+20,!0),t.getUint32(e+24,!0),t.getUint32(e+28,!0)].some(o=>o!==0))throw new u("E_GROUP_RANGE",`V3 external variant ${n} must use zero inline geometry offsets`)}function rt(t,e,n,r,o,s){const i=se(t,e,n,t.byteLength,o,s);if(i.chunk.count!==r)throw new u("E_GROUP_RANGE",`${o} vertex_count mismatch: manifest=${r}, sidecar=${i.chunk.count}`);return i}function It(t){return"normal"in t?t.normal:t}function Gn(t,e,n){const r=It(t),o=new DataView(e);let s=0;const i=rt(e,o,s,r.line_count,`V3 external variant ${t.id} line blob`,n);s=i.offset;const a=rt(e,o,s,r.fill_count,`V3 external variant ${t.id} fill blob`,n);s=a.offset;const c=rt(e,o,s,r.dot_count,`V3 external variant ${t.id} dot blob`,n);if(s=c.offset,s!==e.byteLength)throw new u("E_GROUP_RANGE",`V3 external variant ${t.id} sidecar has trailing bytes`);return{line:{chunk:i.chunk,snapshot:i.snapshot},fill:{chunk:a.chunk,snapshot:a.snapshot},dot:{chunk:c.chunk,snapshot:c.snapshot}}}function Un(t,e){const n=je(e),r=We(n,257,"BLOCK_NORMAL_GEOMETRY"),o=new DataView(e);let s=r.offset;const i=r.offset+r.length,a=O(n.versionMinor),c=rt(e,o,s,t.normal.line_count,`V3.3 external variant ${t.id} normal line blob`,a);s=c.offset;const l=rt(e,o,s,t.normal.fill_count,`V3.3 external variant ${t.id} normal fill blob`,a);s=l.offset;const m=rt(e,o,s,t.normal.dot_count,`V3.3 external variant ${t.id} normal dot blob`,a);if(s=m.offset,s!==i)throw new u("E_GROUP_RANGE",`V3.3 external variant ${t.id} normal geometry section has trailing bytes`);return{line:{chunk:c.chunk,snapshot:c.snapshot},fill:{chunk:l.chunk,snapshot:l.snapshot},dot:{chunk:m.chunk,snapshot:m.snapshot}}}function Cn(t,e,n="u8"){if(e.byteLength!==t.raw_size)throw new u("E_GROUP_RANGE",`V3 external variant ${t.id} raw_size mismatch: manifest=${t.raw_size}, sidecar=${e.byteLength}`);return"normal"in t?Un(t,e):Gn(t,e,n)}function Pn(t,e,n){const r=e==null?void 0:e.get(t.id);if(!r)throw new u("E_GROUP_RANGE",`Missing V3 external sidecar buffer for variant ${t.id}`);return Cn(t,r,n)}function Rt(t,e,n,r,o){if(r===0)return 0;if(at(n,r,e.length,o),r<4)throw new u("E_GROUP_RANGE",`Missing ${o} vertex_count`);return t.getUint32(e.offset+n,!0)}function Sn(t,e,n,r){const o=n.offset+n.length;let s=n.offset;const i=ft(t,e,s,o,"V3 BASE_GEOMETRY line",r);s=i.offset;const a=ft(t,e,s,o,"V3 BASE_GEOMETRY fill",r);s=a.offset;const c=ft(t,e,s,o,"V3 BASE_GEOMETRY dot",r);if(s=c.offset,s!==o)throw new u("E_GROUP_RANGE","V3 BASE_GEOMETRY has trailing bytes");return{line:i.chunk,fill:a.chunk,dot:c.chunk}}function Vt(t){return ke(t.pos,t.count,2)}function Tn(t,e,n){return Gt(Gt(Vt(t),Vt(e)),Vt(n))}function ae(t){return"normal"in t?bn(t.normal.bbox??t.normal.own_bbox??null):null}function Bn(t,e,n,r,o,s,i,a){if(n.length%60!==0)throw new u("E_GROUP_RANGE","V3 VARIANT_TABLE length must be a multiple of 60");const c=[],l=new Map,m=[],g=n.length/60;for(let d=0;d<g;d+=1){const h=n.offset+d*60,w=e.getUint32(h,!0),y=e.getUint32(h+4,!0),f=(s==null?void 0:s[d])??null,_=!f||!a.requiredExternalVariantIds||a.requiredExternalVariantIds.has(d),b=Nn(a,f,_),E=f?(ie(e,h,d),!_||b?Vn(i):Pn(f,a.externalVariantBuffers,i)):{line:At(t,e,r,e.getUint32(h+8,!0),e.getUint32(h+12,!0),`V3 variant ${d} line blob`,i),fill:At(t,e,r,e.getUint32(h+16,!0),e.getUint32(h+20,!0),`V3 variant ${d} fill blob`,i),dot:At(t,e,r,e.getUint32(h+24,!0),e.getUint32(h+28,!0),`V3 variant ${d} dot blob`,i)},p=f?It(f):null,T=(p==null?void 0:p.line_count)??E.line.chunk.count,N=(p==null?void 0:p.fill_count)??E.fill.chunk.count,P=(p==null?void 0:p.dot_count)??E.dot.chunk.count,G=f&&(!_||b)?ae(f):Tn(E.line.chunk,E.fill.chunk,E.dot.chunk),U={id:d,name:lt(o,w,y,`V3 variant ${d} name`),line_count:b?T:E.line.chunk.count,fill_count:b?N:E.fill.chunk.count,dot_count:b?P:E.dot.chunk.count,sourceLineCount:T,sourceFillCount:N,sourceDotCount:P,nestedStart:e.getUint32(h+32,!0),nestedCount:e.getUint32(h+36,!0),textStart:e.getUint32(h+40,!0),textCount:e.getUint32(h+44,!0),precisionOriginX:e.getFloat32(h+48,!0),precisionOriginY:e.getFloat32(h+52,!0),lineSnapshot:E.line.snapshot,fillSnapshot:E.fill.snapshot,dotSnapshot:E.dot.snapshot,bbox:G};c.push(U),l.set(d,{line:E.line.chunk,fill:E.fill.chunk,dot:E.dot.chunk}),m.push({line:E.line.snapshot,fill:E.fill.snapshot,dot:E.dot.snapshot})}return{variantsById:c,variants:l,snapshots:m}}function $n(t,e,n,r,o){if(e.length%60!==0)throw new u("E_GROUP_RANGE","V3 VARIANT_TABLE length must be a multiple of 60");const s=[],i=e.length/60;for(let a=0;a<i;a+=1){const c=e.offset+a*60,l=t.getUint32(c,!0),m=t.getUint32(c+4,!0),g=(o==null?void 0:o[a])??null;g&&ie(t,c,a);const d=g?It(g):null,h=t.getFloat32(c+48,!0),w=t.getFloat32(c+52,!0);s.push({id:a,name:lt(r,l,m,`V3 variant ${a} name`),line_count:g?d.line_count:Rt(t,n,t.getUint32(c+8,!0),t.getUint32(c+12,!0),`V3 variant ${a} line blob`),fill_count:g?d.fill_count:Rt(t,n,t.getUint32(c+16,!0),t.getUint32(c+20,!0),`V3 variant ${a} fill blob`),dot_count:g?d.dot_count:Rt(t,n,t.getUint32(c+24,!0),t.getUint32(c+28,!0),`V3 variant ${a} dot blob`),nestedStart:t.getUint32(c+32,!0),nestedCount:t.getUint32(c+36,!0),textStart:t.getUint32(c+40,!0),textCount:t.getUint32(c+44,!0),precisionOriginX:h,precisionOriginY:w,bbox:g?ae(g):null})}return s}function mt(t,e,n){if(e.length%32!==0)throw new u("E_GROUP_RANGE",`${n} length must be a multiple of 32`);const r=new DataView(t),o=[];for(let s=e.offset;s<e.offset+e.length;s+=32){const i=r.getUint16(s+30,!0);Hn(i),o.push({variantId:r.getUint32(s,!0),matA:r.getFloat32(s+4,!0),matB:r.getFloat32(s+8,!0),matC:r.getFloat32(s+12,!0),matD:r.getFloat32(s+16,!0),tx:r.getFloat32(s+20,!0),ty:r.getFloat32(s+24,!0),insLayerIdx:r.getUint16(s+28,!0),flags:i})}return o}function On(t,e,n){const r=t.getUint32(e,!0),o=t.getUint32(e+4,!0),s=t.getUint8(e+42),i=t.getUint8(e+43),a=t.getFloat32(e+24,!0),c=t.getFloat32(e+28,!0);return{t:lt(n,r,o,"V3 text value"),x:t.getFloat32(e+8,!0),y:t.getFloat32(e+12,!0),h:t.getFloat32(e+16,!0),r:t.getFloat32(e+20,!0),c:[t.getUint8(e+36),t.getUint8(e+37),t.getUint8(e+38)],li:t.getUint16(e+40,!0),ha:en[s&3]??"left",va:nn[s>>2&3]??"alphabetic",lh:t.getFloat32(e+32,!0),...a?{w:a}:{},...c!==1?{wf:c}:{},...i&1?{mx:!0}:{},...i&2?{my:!0}:{}}}function Nt(t,e,n,r){if(e.length%44!==0)throw new u("E_GROUP_RANGE",`${r} length must be a multiple of 44`);const o=[],s=new DataView(t);for(let i=e.offset;i<e.offset+e.length;i+=44)o.push(On(s,i,n));return o}function vn(t,e){if(t.length%44!==0)throw new u("E_GROUP_RANGE",`${e} length must be a multiple of 44`);return t.length/44}function Mn(t,e,n,r){return{instanceId:n,variantId:e.variantId,matA:t.matA*e.matA+t.matC*e.matB,matB:t.matB*e.matA+t.matD*e.matB,matC:t.matA*e.matC+t.matC*e.matD,matD:t.matB*e.matC+t.matD*e.matD,tx:t.matA*e.tx+t.matC*e.ty+t.tx,ty:t.matB*e.tx+t.matD*e.ty+t.ty,insLayerIdx:r}}function Dn(t,e,n,r){var y;const o=((y=r[e.insLayerIdx])==null?void 0:y.visible)===!1,s=e.matA*t.x+e.matC*t.y+e.tx,i=e.matB*t.x+e.matD*t.y+e.ty,a=Math.hypot(e.matA,e.matB),c=Math.hypot(e.matC,e.matD),l=c>1e-12?c:a>1e-12?a:1,m=a>1e-12&&l>1e-12?a/l:1,g=kn(t,e),{mx:d,my:h,...w}=t;return{...w,x:s,y:i,h:t.h*l,w:t.w===void 0?void 0:t.w*l,wf:(t.wf??1)*m,r:g.r,...g.mx?{mx:!0}:{},...g.my?{my:!0}:{},li:o||t.li===n?e.insLayerIdx:t.li}}function kn(t,e){const n=t.r*Math.PI/180,r=Math.cos(n),o=Math.sin(n),s=t.mx?-1:1,i=t.my?-1:1,a=s*(e.matA*r+e.matC*o),c=s*(e.matB*r+e.matD*o),l=i*(e.matC*r-e.matA*o),m=i*(e.matD*r-e.matB*o),g=a*m-c*l,d=Math.atan2(c,a)*180/Math.PI;return g<0?{r:Math.atan2(-c,-a)*180/Math.PI,mx:!0}:{r:d}}function Ln(t,e){return t===e?e:t}function Fn(t,e,n){return t===n?e:t}function Xn(t,e){const n=new DataView(t),{versionMinor:r,sections:o}=xn(t),s=O(r),i=q(o,1,"SCENE_META"),a=q(o,2,"LAYER_TABLE"),c=q(o,3,"STRING_TABLE"),l=q(o,4,"BASE_GEOMETRY"),m=q(o,5,"VARIANT_TABLE"),g=q(o,6,"VARIANT_GEOMETRY"),d=q(o,7,"SCENE_INSTANCE_TABLE"),h=pt(o,8),w=pt(o,9),y=pt(o,10),f=_n(t,i,"SCENE_META"),_=En(f)?An(f,m.length/60):null,b=wn(f),E=b?In(f):null,p=pn(f,_,b),T=b?"nested_instanced_external_annotations":_?"nested_instanced_external":"nested_instanced",N=new Uint8Array(t,c.offset,c.length),P=Rn(t,a,N),G=Number(f.layer0_index??0),U=Qt({bounds:f.bounds??[0,0,0,0],entity_count:Number(f.entity_count??0),line_count:Number(f.base_line_count??0),fill_count:Number(f.base_fill_count??0),dot_count:Number(f.base_dot_count??0),layers:P,texts:[]});zn(G,U.layers);const R=Sn(t,n,l,s);if(!e.loadBlocks){const x=$n(n,m,g,N,_),A=mt(t,d,"V3 SCENE_INSTANCE_TABLE"),M=mt(t,h,"V3 NESTED_INSTANCE_TABLE"),S=Nt(t,w,N,"V3 SCENE_TEXT_TABLE"),B=vn(y,"V3 VARIANT_TEXT_TABLE");if(Number(f.variant_count??x.length)!==x.length)throw new u("E_GROUP_RANGE","V3 variant count mismatch");if(Number(f.scene_instance_count??A.length)!==A.length)throw new u("E_GROUP_RANGE","V3 scene instance count mismatch");if(Number(f.nested_instance_count??M.length)!==M.length)throw new u("E_GROUP_RANGE","V3 nested instance count mismatch");if(Number(f.scene_text_count??S.length)!==S.length)throw new u("E_GROUP_RANGE","V3 scene text count mismatch");if(Number(f.variant_text_count??B)!==B)throw new u("E_GROUP_RANGE","V3 variant text count mismatch");for(const I of x){if(I.nestedStart+I.nestedCount>M.length)throw new u("E_GROUP_RANGE",`V3 variant ${I.id} nested range exceeds table`);if(I.textStart+I.textCount>B)throw new u("E_GROUP_RANGE",`V3 variant ${I.id} text range exceeds table`)}return Zt(A,M,I=>{if(!x[I.variantId])throw new u("E_GROUP_RANGE",`Unknown V3 variantId ${I.variantId}`);de(I.insLayerIdx,P.length)}),{meta:{bounds:f.bounds??[0,0,0,0],entity_count:Number(f.entity_count??0),line_count:R.line.count,fill_count:R.fill.count,dot_count:R.dot.count,version:3,version_minor:r,encoding:T,...p?{features:p}:{},..._?{external_variants:[..._]}:{},...E?{external_annotations:E}:{},layer0_index:G,block_variants:x.map(I=>({id:I.id,name:I.name,line_count:I.line_count,fill_count:I.fill_count,dot_count:I.dot_count})),instance_count:A.length,layers:P,texts:S},header:{...U,lineCount:R.line.count,fillCount:R.fill.count,dotCount:R.dot.count,textCount:S.length,texts:S},decoded:{baseLine:R.line,baseFill:R.fill,baseDot:R.dot,variants:new Map,instances:[],instanceIdByVariantOrdinal:new Map}}}const{variantsById:V,variants:X,snapshots:Y}=Bn(t,n,m,g,N,_,s,e),W=mt(t,d,"V3 SCENE_INSTANCE_TABLE"),v=mt(t,h,"V3 NESTED_INSTANCE_TABLE"),D=Nt(t,w,N,"V3 SCENE_TEXT_TABLE"),$=Nt(t,y,N,"V3 VARIANT_TEXT_TABLE");if(Number(f.variant_count??V.length)!==V.length)throw new u("E_GROUP_RANGE","V3 variant count mismatch");if(Number(f.scene_instance_count??W.length)!==W.length)throw new u("E_GROUP_RANGE","V3 scene instance count mismatch");if(Number(f.nested_instance_count??v.length)!==v.length)throw new u("E_GROUP_RANGE","V3 nested instance count mismatch");if(Number(f.scene_text_count??D.length)!==D.length)throw new u("E_GROUP_RANGE","V3 scene text count mismatch");if(Number(f.variant_text_count??$.length)!==$.length)throw new u("E_GROUP_RANGE","V3 variant text count mismatch");for(const x of V){if(x.nestedStart+x.nestedCount>v.length)throw new u("E_GROUP_RANGE",`V3 variant ${x.id} nested range exceeds table`);if(x.textStart+x.textCount>$.length)throw new u("E_GROUP_RANGE",`V3 variant ${x.id} text range exceeds table`)}Zt(W,v,x=>{if(!V[x.variantId])throw new u("E_GROUP_RANGE",`Unknown V3 variantId ${x.variantId}`);de(x.insLayerIdx,P.length)});const Ae=new Map;for(const x of V)Ae.set(x.id,$.slice(x.textStart,x.textStart+x.textCount));const ht=[],L=e.externalVariantDeltaOnly,Ie=L?[]:[...D],vt=new Map,gt=new Map,Re=new Map,$r=(x,A)=>{vt.set(x,Gt(vt.get(x)??null,A))},Ve=(x,A,M,S,B,Z)=>{var Se;if(B>64)throw new u("E_GROUP_RANGE","V3 nested instance depth exceeds limit");if(Z.has(x))throw new u("E_GROUP_RANGE",`V3 nested variant cycle detected at ${x}`);const I=V[x];if(!I)throw new u("E_GROUP_RANGE",`Unknown V3 variantId ${x}`);Z.add(x);const Q=!e.requiredExternalVariantIds||e.requiredExternalVariantIds.has(x),H=L?((Se=e.requiredExternalVariantIds)==null?void 0:Se.has(x))===!0:Q;let F=!1;const Pe=!!(I.line_count||I.fill_count||I.dot_count),Mr=I.textCount>0;if(H&&(Pe||Mr)&&(ht.push({instanceId:A.instanceId,variantId:x,matA:A.matA,matB:A.matB,matC:A.matC,matD:A.matD,tx:A.tx,ty:A.ty,insLayerIdx:A.insLayerIdx}),Pe&&$r(A.instanceId,I.bbox?ce(I.bbox,A):null),F=!0),H){I.textCount>0&&(F=!0);for(let tt=0;tt<I.textCount;tt+=1){const ot=Dn($[I.textStart+tt],A,G,U.layers);Ie.push({...ot,iv:M,io:S})}}for(let tt=0;tt<I.nestedCount;tt+=1){const ot=v[I.nestedStart+tt],Dr=Fn(ot.insLayerIdx,A.insLayerIdx,G),kr=Yn(ot,I,V[ot.variantId]),Lr=Mn(A,kr,A.instanceId,Dr);F=Ve(ot.variantId,Lr,M,S,B+1,Z)||F}return Z.delete(x),F},Mt=new Map;W.forEach((x,A)=>{if(!V[x.variantId])throw new u("E_GROUP_RANGE",`Unknown V3 scene variantId ${x.variantId}`);const S=Re.get(x.variantId)??0;Re.set(x.variantId,S+1),gt.set(`${x.variantId}:${S}`,A);const B=Ln(x.insLayerIdx,G),Z={instanceId:A,variantId:x.variantId,matA:x.matA,matB:x.matB,matC:x.matC,matD:x.matD,tx:x.tx,ty:x.ty,insLayerIdx:B},I=Ve(x.variantId,Z,x.variantId,S,0,new Set);if(L&&!I)return;let Q=Mt.get(B);Q||(Q=new Map,Mt.set(B,Q));let H=Q.get(x.variantId);H||(H={count:0,bboxes:[],inserts:[]},Q.set(x.variantId,H)),H.count+=1;const F=vt.get(A)??null;F&&H.bboxes.push(F),H.inserts.push({instanceId:A,variantId:x.variantId,label:`#${A+1} (${x.tx.toFixed(1)}, ${x.ty.toFixed(1)})`,tx:x.tx,ty:x.ty,canHighlight:F!==null,...F?{bbox:F}:{}})});const Ne=new Map;for(const[x,A]of Mt){const M=[];for(const[S,B]of A)M.push({variantId:S,blockName:ee(V[S],S),instanceCount:B.count,bboxes:B.bboxes,inserts:B.inserts});M.sort((S,B)=>B.instanceCount-S.instanceCount),Ne.set(x,M)}let Ge=L?0:R.line.count,Ue=L?0:R.fill.count,Ce=L?0:R.dot.count;for(const x of ht){const A=V[x.variantId];!(e.deferExternalVariantGeometry&&A.lineSnapshot.count===0&&A.fillSnapshot.count===0&&A.dotSnapshot.count===0)&&!te(x.instanceId,e)||(Ge+=A.line_count,Ue+=A.fill_count,Ce+=A.dot_count)}const yt=ln(Ie,gt,e),Or={bounds:f.bounds??[0,0,0,0],entity_count:L?0:Number(f.entity_count??0),line_count:R.line.count,fill_count:R.fill.count,dot_count:R.dot.count,version:3,version_minor:r,encoding:T,...p?{features:p}:{},..._?{external_variants:[..._]}:{},...E?{external_annotations:E}:{},layer0_index:G,block_variants:V.map(x=>({id:x.id,name:x.name,line_count:x.sourceLineCount,fill_count:x.sourceFillCount,dot_count:x.sourceDotCount})),instance_count:W.length,layers:P,texts:yt},vr={...U,entityCount:L?0:U.entityCount,lineCount:Ge,fillCount:Ue,dotCount:Ce,textCount:yt.length,texts:yt,...e.loadBlocks?{layerBlockUsages:Ne,insertRuntime:dn(G,V,Y,Ae,ht,yt,gt)}:{}};return{meta:Or,header:vr,decoded:{baseLine:L?Ct():R.line,baseFill:L?Ct():R.fill,baseDot:L?Ct():R.dot,variants:X,instances:ht,instanceIdByVariantOrdinal:gt}}}function Gt(t,e){return Yt(t,e)}function ce(t,e){return zt(t,e)}function ue(t){return Le(t)}function le(t,e){return Fe(t,e)}function fe(t,e){return ce(t,{variantId:e.variantId,matA:e.matA,matB:e.matB,matC:e.matC,matD:e.matD,tx:e.tx,ty:e.ty,insLayerIdx:e.insLayerIdx})}function Yn(t,e,n){if(!(n!=null&&n.bbox)||!e.bbox)return t;const r=e.precisionOriginX,o=e.precisionOriginY;if(!Number.isFinite(r)||!Number.isFinite(o)||r===0&&o===0)return t;const s={...t,tx:t.tx-r,ty:t.ty-o},i=fe(n.bbox,t),a=fe(n.bbox,s),c=Math.max(ue(e.bbox),ue(n.bbox),1),l=Math.hypot(r,o),m=Math.hypot(t.tx,t.ty),g=Math.hypot(s.tx,s.ty);if(l<=c*16||m<=c*16)return t;const d=le(e.bbox,i),h=le(e.bbox,a);return d>c*16&&h*4<d&&g*4<m?s:t}function de(t,e){if(t>=e)throw new u("E_GROUP_RANGE",`Instance layer index ${t} exceeds layer count ${e}`)}function zn(t,e){if(!Number.isInteger(t)||t<0||t>=e.length)throw new u("E_GROUP_RANGE",`layer0_index out of range: ${t}`);if(e[t].name!=="0")throw new u("E_GROUP_RANGE",`layer0_index must reference layer "0": ${t}`)}function Hn(t){if(t!==0)throw new u("E_GROUP_RANGE",`Instance flags must be zero for Stage 1, found ${t}`)}function*Kn(t,e,n,r,o){let s=n;const i=[{kind:"line",count:r.lineCount},{kind:"fill",count:r.fillCount},{kind:"dot",count:r.dotCount}];for(const a of i){const c=De(t,e,s,a.count);for(;;){const l=c.next();if(l.done){s=l.value;break}yield{kind:a.kind,payload:l.value}}}if(s!==t.byteLength)throw new u("E_GROUP_RANGE",`Trailing bytes detected: offset=${s}, size=${t.byteLength}`);for(const a of r.texts)yield{kind:"text",payload:a}}function*jn(t,e,n,r){yield*Kn(t,e,n,r)}function*Ut(t,e,n,r,o,s,i,a){if(un(a,t,Math.max(0,e-n.count)),e===0){yield{kind:t,payload:qe()};return}const c=C;let l=new Float32Array(c*2),m=[],g=0,d=0;const h=function*(){if(g<=0)return;const f=g===c?{pos:l,count:g,segments:Jt(m)}:{pos:l.slice(0,g*2),count:g,segments:Jt(m)};yield{kind:t,payload:f},d+=g,g=0,l=new Float32Array(c*2),m=[]},w=(f,_,b,E)=>{if(f<=0)return;const p=m[m.length-1];if(p&&p.startVertex+p.vertexCount===g&&p.layerIndex===b&&p.color[0]===_[0]&&p.color[1]===_[1]&&p.color[2]===_[2]&&p.lineweightPx===E){m[m.length-1]={...p,vertexCount:p.vertexCount+f};return}m.push({startVertex:g,vertexCount:f,color:[_[0],_[1],_[2]],layerIndex:b,...E===void 0?{}:{lineweightPx:E}})};yield*function*(){for(const f of Et(n)){let _=f.startVertex;const b=f.startVertex+f.vertexCount;for(;_<b;){const E=Math.min(c-g,b-_),p=_*2,T=g*2;l.set(n.pos.subarray(p,p+E*2),T),w(E,f.color,f.layerIndex,f.lineweightPx),_+=E,g+=E,g===c&&(yield*h())}}}();for(const f of o){if(!te(f.instanceId,a))continue;const _=r.get(f.variantId);if(!_)throw new u("E_GROUP_RANGE",`Unknown variantId ${f.variantId}`);const b=_[t],E=i[f.insLayerIdx].visible===!1;for(const p of Et(b)){const T=E||p.layerIndex===s?f.insLayerIdx:p.layerIndex;let N=p.startVertex;const P=p.startVertex+p.vertexCount;for(;N<P;){const G=Math.min(c-g,P-N);for(let U=0;U<G;U+=1){const R=(N+U)*2,V=(g+U)*2,X=b.pos[R],Y=b.pos[R+1];l[V]=f.matA*X+f.matC*Y+f.tx,l[V+1]=f.matB*X+f.matD*Y+f.ty}w(G,p.color,T,p.lineweightPx),N+=G,g+=G,g===c&&(yield*h())}}}if(yield*h(),d!==e)throw new u("E_GROUP_RANGE",`Expanded ${t} count mismatch: header=${e}, emitted=${d}`)}function*Wn(t,e,n,r){yield*Ut("line",e.lineCount,t.baseLine,t.variants,t.instances,n.layer0_index,e.layers,r),yield*Ut("fill",e.fillCount,t.baseFill,t.variants,t.instances,n.layer0_index,e.layers,r),yield*Ut("dot",e.dotCount,t.baseDot,t.variants,t.instances,n.layer0_index,e.layers,r);for(const o of e.texts)yield{kind:"text",payload:o}}function qn(t,e){const n=an(e),r=Xn(t,n);return{header:r.header,chunks:Wn(r.decoded,r.header,{layer0_index:r.meta.layer0_index??0},n)}}function Jn(t,e){if(yn(t))return qn(t,e);const n=gn(t);return{header:n.header,chunks:jn(t,n.view,n.dataOffset,n.header)}}function Ct(){return{pos:new Float32Array(0),col:new Uint8Array(0),lay:new Uint8Array(0),count:0}}function Zn(t,e){return t?ct(zt(t,e)):null}async function Qn(t){const e=me(),n=t.fetchImpl??fetch,r=new Map(t.entries.map(l=>[l.id,l])),o=Array.from(new Set(t.requiredVariantIds)).sort((l,m)=>l-m),s=new Map,i=tr(t.concurrency);let a=0;async function c(){for(;a<o.length;){const l=o[a++],m=r.get(l);if(!m)throw new Error(`External block ${l} is missing from manifest`);const g=new URL(m.href,t.baseUrl).href,d=await n(g,{signal:t.signal});if(!d.ok){const w="status"in d?d.status:void 0,y="statusText"in d?d.statusText:void 0,f=[w,y].filter(_=>_!==void 0&&_!=="").join(" ");throw new Error(`External block ${l} fetch failed${f?`: ${f}`:""}`)}const h=await d.arrayBuffer();if(h.byteLength!==m.raw_size)throw new Error(`External block ${l} raw_size mismatch: manifest=${m.raw_size}, response=${h.byteLength}`);s.set(l,h)}}return await Promise.all(Array.from({length:Math.min(i,o.length)},c)),{buffers:s,fetchMs:me()-e}}function tr(t){const e=Math.floor(t??3);return Number.isFinite(e)?Math.max(1,Math.min(e,8)):3}function me(){var t,e;return((e=(t=globalThis.performance)==null?void 0:t.now)==null?void 0:e.call(t))??Date.now()}class er{constructor(){Be(this,j,new Map)}get size(){return st(this,j).size}append(e){let n=0;for(const r of e){if(r.count<=0)continue;const o=St(r.layerIndex,r.lineweightPx);let s=st(this,j).get(o),i=r.pos,a=r.positionItemSize;const c=r.linePositionKind??null;s?s.positionItemSize!==a&&(ye(s),a!==3&&(i=ge(i,r.count,a)),s.positionItemSize=3,a=3,s.linePositionKind=null):(s={layerIndex:r.layerIndex,...r.lineweightPx===void 0?{}:{lineweightPx:r.lineweightPx},posParts:[],positionItemSize:a,colParts:[],colorRunParts:[],linePositionKind:c,count:0,bbox:null},st(this,j).set(o,s));const l=s.count>0;s.posParts.push(i),s.colParts.push(r.col);const m=ur(r.colorRuns??lr(r.col),s.count);s.colorRunParts.push(m),s.linePositionKind!==c&&(s.linePositionKind=null),s.positionItemSize===2&&s.linePositionKind===null&&ye(s),s.count+=r.count,s.bbox=l&&s.bbox===null?null:rr(s.bbox,r.bbox),n+=r.count}return n}drain(){const e=[];for(const n of st(this,j).values()){if(n.count<=0)continue;const r=n.posParts.length===1?n.posParts[0]:ar(n.posParts,n.count*n.positionItemSize),o=n.colParts.length===1?n.colParts[0]:cr(n.colParts,n.count*3),s=xe(n.colorRunParts.flat()),i={layerIndex:n.layerIndex,pos:r,positionItemSize:n.positionItemSize,col:o,count:n.count,bbox:ct(n.bbox),colorRuns:s};n.lineweightPx!==void 0&&(i.lineweightPx=n.lineweightPx),n.linePositionKind&&(i.linePositionKind=n.linePositionKind),e.push(i)}return st(this,j).clear(),e}}j=new WeakMap;function Pt(){return new er}function nr(){return{line:Pt(),fill:Pt(),dot:Pt()}}function rr(t,e){const n=ct(e);return t?n?{minX:Math.min(t.minX,n.minX),minY:Math.min(t.minY,n.minY),maxX:Math.max(t.maxX,n.maxX),maxY:Math.max(t.maxY,n.maxY)}:null:n}function he(t,e={}){if(t.count<=0)return[];const n=Et(t),r=[],o=new Map,s=new Map,i=new Map,a=e.markLinePositionXy===!0||e.splitLineweight===!0;for(const y of n){if(y.vertexCount<=0)continue;const f=y.layerIndex,_=a?y.lineweightPx:void 0,b=St(f,_),E=o.get(b);E===void 0?(o.set(b,y.vertexCount),s.set(b,f),i.set(b,_),r.push(b)):o.set(b,E+y.vertexCount)}const c=new Map,l=new Map,m=new Map,g=new Set,d=e.markLinePositionXy===!0?"xy-zero-z":void 0,h=d?2:3;for(const y of r){const f=s.get(y),_=i.get(y),b=o.get(y)??0,E={layerIndex:f,..._===void 0?{}:{lineweightPx:_},pos:new Float32Array(b*h),positionItemSize:h,col:new Uint8Array(b*3),count:b,bbox:null,colorRuns:[]};d&&(E.linePositionKind=d),c.set(y,E),l.set(y,0),m.set(y,null)}for(const y of n){if(y.vertexCount<=0)continue;const f=y.layerIndex,_=a?y.lineweightPx:void 0,b=St(f,_),E=c.get(b),p=l.get(b),T=p,N=y.color[0],P=y.color[1],G=y.color[2];for(let U=0;U<y.vertexCount;U+=1){const R=y.startVertex+U,V=p+U,X=V*h,Y=V*3,W=R*2,v=t.pos[W],D=t.pos[W+1];E.pos[X]=v,E.pos[X+1]=D,h===3&&(E.pos[X+2]=0),E.col[Y]=N,E.col[Y+1]=P,E.col[Y+2]=G;const $=m.get(b);!Number.isFinite(v)||!Number.isFinite(D)?g.add(b):$?(v<$.minX&&($.minX=v),D<$.minY&&($.minY=D),v>$.maxX&&($.maxX=v),D>$.maxY&&($.maxY=D)):m.set(b,{minX:v,minY:D,maxX:v,maxY:D})}E.colorRuns.push({startVertex:T,vertexCount:y.vertexCount,color:[N,P,G]}),l.set(b,p+y.vertexCount)}const w=[];for(const y of r){const f=c.get(y);f&&(f.bbox=g.has(y)?null:ct(m.get(y)??null),f.colorRuns=xe(f.colorRuns??[]),w.push(f))}return w}function St(t,e){return e===void 0?`${t}:`:`${t}:${e}`}function or(t,e){return t.append(e)}function sr(t){return t.drain()}function ir(t){const e=[],n=new Set;for(const r of t)_e(e,n,r.pos.buffer),_e(e,n,r.col.buffer);return e}function ar(t,e){const n=new Float32Array(e);let r=0;for(const o of t)n.set(o,r),r+=o.length;return n}function ge(t,e,n){if(n===3)return t;const r=new Float32Array(e*3);for(let o=0;o<e;o+=1){const s=o*2,i=o*3;r[i]=t[s]??0,r[i+1]=t[s+1]??0,r[i+2]=0}return r}function ye(t){if(t.positionItemSize===3)return;const e=t.positionItemSize;t.posParts=t.posParts.map(n=>ge(n,n.length/e,e)),t.positionItemSize=3,t.linePositionKind=null}function cr(t,e){const n=new Uint8Array(e);let r=0;for(const o of t)n.set(o,r),r+=o.length;return n}function ur(t,e){return t.map(n=>({startVertex:n.startVertex+e,vertexCount:n.vertexCount,color:[n.color[0],n.color[1],n.color[2]]}))}function xe(t){const e=[];for(const n of t){const r=e[e.length-1];if(r&&r.startVertex+r.vertexCount===n.startVertex&&r.color[0]===n.color[0]&&r.color[1]===n.color[1]&&r.color[2]===n.color[2]){e[e.length-1]={...r,vertexCount:r.vertexCount+n.vertexCount};continue}e.push({startVertex:n.startVertex,vertexCount:n.vertexCount,color:[n.color[0],n.color[1],n.color[2]]})}return e}function lr(t){const e=Math.floor(t.length/3),n=[];let r=0;for(;r<e;){const o=r*3,s=t[o]??0,i=t[o+1]??0,a=t[o+2]??0;let c=r+1;for(;c<e;){const l=c*3;if(t[l]!==s||t[l+1]!==i||t[l+2]!==a)break;c+=1}n.push({startVertex:r,vertexCount:c-r,color:[s,i,a]}),r=c}return n}function _e(t,e,n){n instanceof ArrayBuffer&&(e.has(n)||(e.add(n),t.push(n)))}function fr(t,e,n="u8"){if(e<=0&&t.byteLength===0)return{pos:new Float32Array(0),count:0,segments:[]};const{buffer:r,startOffset:o,endOffset:s}=gr(t),i=new DataView(r),a=Ft(r,i,o,e,s,n);if(a.offset!==s)throw new u("E_GROUP_RANGE",`Insert runtime geometry chunk has trailing bytes: offset=${a.offset-o}, length=${t.byteLength}`);return a.chunk}function dr(t){const e=n=>{const r=t[n],o=fr(r.raw,r.count,r.groupLayerEncoding),s=he(o,{splitLineweight:n==="line"}),i=new Map;for(const a of s)i.set(mr(a.layerIndex,a.lineweightPx),{layerIndex:a.layerIndex,...a.lineweightPx===void 0?{}:{lineweightPx:a.lineweightPx},pos:a.pos,col:a.col,count:a.count,bbox:it(a.bbox)});return i};return{line:e("line"),fill:e("fill"),dot:e("dot")}}function mr(t,e){return e===void 0?`${t}:`:`${t}:${e}`}function hr(t,e){let n=e?it(e):null;for(const r of["line","fill","dot"])for(const o of t[r].values())n=Yt(n,o.bbox);return n}function gr(t){if(t.buffer instanceof ArrayBuffer)return{buffer:t.buffer,startOffset:t.byteOffset,endOffset:t.byteOffset+t.byteLength};const e=Uint8Array.from(t);return{buffer:e.buffer,startOffset:e.byteOffset,endOffset:e.byteOffset+e.byteLength}}function yr(t){const e=t.insertRuntime;if(!e||e.instances.length===0)return null;const n=[],r=new Map,o=new Set;for(const c of e.variants){const l=dr(c),m=Tt(l.line),g=Tt(l.fill),d=Tt(l.dot),h=m.length>0||g.length>0||d.length>0;r.set(c.id,h?hr(l,null):null),h&&(o.add(c.id),n.push({variantId:c.id,line:m,fill:g,dot:d}))}const s=e.instances.filter(c=>o.has(c.variantId));if(s.length===0)return null;const i=Er(s,r),a=pr(n,i);return{variants:n,instances:i,bytes:a,cost:i.count}}function xr(t){const e=[],n=new Set,r=o=>{n.has(o)||(n.add(o),e.push(o))};r(t.instances.meta.buffer),r(t.instances.mats.buffer),r(t.instances.bboxes.buffer);for(const o of t.variants)$t(o.line,r),$t(o.fill,r),$t(o.dot,r);return e}function Tt(t){const e=[];for(const n of t.values())n.count<=0||e.push(_r(n));return e}function _r(t){return{pos:t.pos,col:t.col,count:t.count,layerIndex:t.layerIndex,...t.lineweightPx===void 0?{}:{lineweightPx:t.lineweightPx},bbox:t.bbox}}function Er(t,e){const n=t.length,r=new Uint32Array(n*3),o=new Float32Array(n*6),s=new Float32Array(n*4);for(let i=0;i<n;i+=1){const a=t[i],c=i*3;r[c]=a.instanceId,r[c+1]=a.variantId,r[c+2]=a.insLayerIdx;const l=i*6;o[l]=a.matA,o[l+1]=a.matB,o[l+2]=a.matC,o[l+3]=a.matD,o[l+4]=a.tx,o[l+5]=a.ty;const m=Zn(e.get(a.variantId)??null,a);wr(s,i*4,m)}return{meta:r,mats:o,bboxes:s,count:n}}function wr(t,e,n){if(!n){t[e]=Number.POSITIVE_INFINITY,t[e+1]=Number.POSITIVE_INFINITY,t[e+2]=Number.NEGATIVE_INFINITY,t[e+3]=Number.NEGATIVE_INFINITY;return}t[e]=n.minX,t[e+1]=n.minY,t[e+2]=n.maxX,t[e+3]=n.maxY}function pr(t,e){let n=e.meta.byteLength+e.mats.byteLength+e.bboxes.byteLength;for(const r of t)n+=Bt(r.line),n+=Bt(r.fill),n+=Bt(r.dot);return n}function Bt(t){return t.reduce((e,n)=>e+n.pos.byteLength+n.col.byteLength,0)}function $t(t,e){for(const n of t)e(n.pos.buffer),e(n.col.buffer)}function Ee(){return typeof performance<"u"&&typeof performance.now=="function"?performance.now():Date.now()}class br{constructor(){et(this,"geometryCredits",0);et(this,"textCredits",0);et(this,"cancelled",!1);et(this,"geometryWaiters",[]);et(this,"textWaiters",[])}grant(e){this.cancelled||(this.geometryCredits+=Math.max(0,e.geometryCredits),this.textCredits+=Math.max(0,e.textCredits),this.flushWaiters())}cancel(){if(!this.cancelled){this.cancelled=!0,this.geometryCredits=0,this.textCredits=0;for(const e of this.geometryWaiters.splice(0,this.geometryWaiters.length))e(!1);for(const e of this.textWaiters.splice(0,this.textWaiters.length))e(!1)}}take(e){return this.cancelled?Promise.resolve(!1):e==="geometry"&&this.geometryCredits>0?(this.geometryCredits-=1,Promise.resolve(!0)):e==="text"&&this.textCredits>0?(this.textCredits-=1,Promise.resolve(!0)):new Promise(n=>{this.getWaiters(e).push(n)})}flushWaiters(){this.flushKind("geometry"),this.flushKind("text")}flushKind(e){const n=this.getWaiters(e);for(;n.length>0&&this.getCredits(e)>0;){this.setCredits(e,this.getCredits(e)-1);const r=n.shift();r==null||r(!0)}}getCredits(e){return e==="geometry"?this.geometryCredits:this.textCredits}setCredits(e,n){if(e==="geometry"){this.geometryCredits=n;return}this.textCredits=n}getWaiters(e){return e==="geometry"?this.geometryWaiters:this.textWaiters}}const we=262144,Ar=Number.MAX_SAFE_INTEGER,pe=524288,Ir=Number.MAX_SAFE_INTEGER,Rr=5e6,Vr=64,J=self;let z=null;async function Ot(t,e,n){const r=sr(e);if(!r.length||!await n.take("geometry"))return 0;const s=r.reduce((a,c)=>a+c.count,0),i={type:"geometry",kind:t,layers:r,cost:s};return J.postMessage(i,ir(r)),s}async function Nr(t,e){return await Ot("line",t.line,e)+await Ot("fill",t.fill,e)+await Ot("dot",t.dot,e)}async function be(t,e){if(!t.length||!await e.take("text"))return 0;const r=t.slice();t.length=0;const o={type:"text",texts:r,cost:r.length};return J.postMessage(o),r.length}function Gr(t){return t.lineCount+t.fillCount+t.dotCount}function Ur(t,e){return Gr(t)>=Rr?{initial:pe,steady:e?pe:Ir}:{initial:we,steady:e?we:Ar}}function Cr(t){return t instanceof Error?t:new Error(String(t))}function Pr(t){if(!(!t||t.length===0))return new Map(t.map(e=>[e.variantId,e.buffer]))}function Sr(t){if(t!==void 0)return new Set(t)}async function Tr(t,e,n){const r=Pr(e);if(!t||!n||n.length===0)return r;const o=Array.from(new Set(n)).filter(a=>!(r!=null&&r.has(a))).sort((a,c)=>a-c);if(o.length===0)return r;const s=await Qn({baseUrl:t.baseUrl,entries:t.entries,requiredVariantIds:o}),i=new Map(r??[]);for(const[a,c]of s.buffers)i.set(a,c);return i}async function Br(t,e,n,r,o=!0,s,i,a,c,l,m,g,d){const h=nr(),w=[];let y=0,f=!1;const _=c===!0,b=typeof i=="number"&&Number.isFinite(i)&&i>=0,E=await Tr(a,l,g),p=Sr(m),T=n&&n.length>0||r===!0||o===!1||s===!0||b||_||E||p!==void 0||d===!0?{...n&&n.length>0?{hiddenInstanceIds:new Set(n)}:{},...r===!0?{keepTextsForHiddenInstances:!0}:{},...o===!1?{loadBlocks:!1}:{},...s===!0?{suppressExpandedInsertGeometry:!0}:{},...b?{maxExpandedInstanceVertices:i}:{},..._?{deferExternalVariantGeometry:!0}:{},...E?{externalVariantBuffers:E}:{},...p!==void 0?{requiredExternalVariantIds:p}:{},...d===!0?{externalVariantDeltaOnly:!0}:{}}:void 0,N=Jn(t,T),P=Ur(N.header,d===!0);J.postMessage({type:"header",header:N.header});const G=async()=>{const V=await Nr(h,e);return y=0,V>0&&(f=!0),V};for(const V of N.chunks){if(V.kind==="text"){w.push(V.payload),w.length>=Vr&&await be(w,e);continue}const X=he(V.payload,{markLinePositionXy:V.kind==="line"});y+=or(h[V.kind],X);const Y=f?P.steady:P.initial;y>=Y&&await G()}await G(),await be(w,e),J.postMessage({type:"done"});const U=Ee(),R=yr(N.header);R&&J.postMessage({type:"insertModel",variants:R.variants,instances:R.instances,cost:R.cost,bytes:R.bytes,planMs:Ee()-U},xr(R)),J.postMessage({type:"complete"})}self.addEventListener("message",t=>{const e=t.data;if(!e)return;if(e.type==="grant"){z==null||z.grant({geometryCredits:e.geometryCredits,textCredits:e.textCredits});return}if(e.type==="cancel"){z==null||z.cancel();return}if(e.type!=="parse")return;const n=new br;z=n,Br(e.buffer,n,e.hiddenInstanceIds,e.keepTextsForHiddenInstances,e.loadBlocks,e.suppressExpandedInsertGeometry,e.maxExpandedInstanceVertices,e.externalVariantFetchSource,e.deferExternalVariantGeometry,e.externalVariantBuffers,e.requiredExternalVariantIds,e.externalVariantGeometryFetchIds,e.externalVariantDeltaOnly).catch(r=>{const o=Cr(r),s=o.code;J.postMessage({type:"error",message:o.message,code:typeof s=="string"?s:void 0})}).finally(()=>{z===n&&(z=null)})})})();
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import type { RenderDebugBreakdownEntry, SplitBlockLayerDetail } from '@nebula-spatial/cad-loader';
|
|
2
|
+
export type CadSessionPhase = 'created' | 'header-ready' | 'initial-loading' | 'interactive' | 'failed' | 'disposed';
|
|
3
|
+
export interface CadWorldBounds {
|
|
4
|
+
readonly minX: number;
|
|
5
|
+
readonly minY: number;
|
|
6
|
+
readonly minZ: number;
|
|
7
|
+
readonly maxX: number;
|
|
8
|
+
readonly maxY: number;
|
|
9
|
+
readonly maxZ: number;
|
|
10
|
+
readonly planar: boolean;
|
|
11
|
+
}
|
|
12
|
+
export type CadLoadSource = ArrayBuffer | string | URL | Pick<File, 'arrayBuffer'> | {
|
|
13
|
+
readonly kind: 'buffer';
|
|
14
|
+
readonly buffer: ArrayBuffer;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: 'url';
|
|
17
|
+
readonly url: string;
|
|
18
|
+
readonly signal?: AbortSignal;
|
|
19
|
+
} | {
|
|
20
|
+
readonly kind: 'packFile';
|
|
21
|
+
readonly file: Pick<File, 'arrayBuffer'>;
|
|
22
|
+
};
|
|
23
|
+
export interface CadFontRequest {
|
|
24
|
+
readonly family?: string;
|
|
25
|
+
readonly styleName?: string;
|
|
26
|
+
readonly shxName?: string;
|
|
27
|
+
readonly weight?: number;
|
|
28
|
+
readonly italic?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface CadResolvedFont {
|
|
31
|
+
readonly fontUrl?: string;
|
|
32
|
+
readonly family?: string;
|
|
33
|
+
readonly fallback: boolean;
|
|
34
|
+
readonly sourceFingerprint?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface CadFontResolver {
|
|
37
|
+
resolve(request: CadFontRequest, signal?: AbortSignal): Promise<CadResolvedFont | null>;
|
|
38
|
+
}
|
|
39
|
+
export interface CadResolvedTextFont {
|
|
40
|
+
readonly text: string;
|
|
41
|
+
readonly fontUrl?: string;
|
|
42
|
+
readonly kind?: string;
|
|
43
|
+
readonly replacedUnsupported: boolean;
|
|
44
|
+
}
|
|
45
|
+
export type ResolveTextFont = (text: string) => CadResolvedTextFont;
|
|
46
|
+
export interface CadTextWarmupOptions {
|
|
47
|
+
/** Idle delay before a scheduled warmup batch flushes. */
|
|
48
|
+
readonly idleDelayMs?: number;
|
|
49
|
+
/** Max unique characters accumulated per font before capping. */
|
|
50
|
+
readonly maxUniqueCharsPerFont?: number;
|
|
51
|
+
/** Per-preload timeout in milliseconds. */
|
|
52
|
+
readonly timeoutMs?: number;
|
|
53
|
+
/** Max remembered warm signatures. */
|
|
54
|
+
readonly signatureCacheLimit?: number;
|
|
55
|
+
}
|
|
56
|
+
export interface CadOpenOptions {
|
|
57
|
+
documentKey?: string;
|
|
58
|
+
filename?: string;
|
|
59
|
+
loadAnnotations?: boolean;
|
|
60
|
+
/** Override the package-relative geometry preparation Worker URL. */
|
|
61
|
+
workerUrl?: string | URL;
|
|
62
|
+
/** Create the geometry preparation Worker. Takes precedence over `workerUrl`. */
|
|
63
|
+
workerFactory?: () => Worker;
|
|
64
|
+
fontResolver?: CadFontResolver;
|
|
65
|
+
resolveTextFont?: ResolveTextFont;
|
|
66
|
+
/**
|
|
67
|
+
* Troika glyph warmup policy passed to the document session. Defaults to
|
|
68
|
+
* enabled; `false` disables background glyph preloading.
|
|
69
|
+
*/
|
|
70
|
+
textWarmup?: boolean | CadTextWarmupOptions;
|
|
71
|
+
}
|
|
72
|
+
export interface CadDocumentHandle {
|
|
73
|
+
readonly documentKey: string | null;
|
|
74
|
+
readonly filename: string | null;
|
|
75
|
+
readonly phase: CadSessionPhase;
|
|
76
|
+
readonly headerBounds: CadWorldBounds | null;
|
|
77
|
+
readonly layerCount: number;
|
|
78
|
+
}
|
|
79
|
+
export interface CadLayerRow {
|
|
80
|
+
readonly index: number;
|
|
81
|
+
readonly name: string;
|
|
82
|
+
readonly visible: boolean;
|
|
83
|
+
readonly color: number | null;
|
|
84
|
+
readonly sourceColor: readonly [number, number, number];
|
|
85
|
+
}
|
|
86
|
+
export interface CadLayerModel {
|
|
87
|
+
readonly rows: readonly CadLayerRow[];
|
|
88
|
+
readonly allColor?: number | null;
|
|
89
|
+
toggle(index: number): void;
|
|
90
|
+
showAll(): void;
|
|
91
|
+
hideAll(): void;
|
|
92
|
+
setColor(index: number, color: number | null): void;
|
|
93
|
+
setAllColor?(color: number | null): void;
|
|
94
|
+
}
|
|
95
|
+
export interface CadBlockUsageRow {
|
|
96
|
+
readonly insertId: string;
|
|
97
|
+
readonly blockName: string;
|
|
98
|
+
readonly layerName: string;
|
|
99
|
+
readonly layerIndex: number;
|
|
100
|
+
readonly variantId: number;
|
|
101
|
+
readonly instanceId: number;
|
|
102
|
+
readonly label: string;
|
|
103
|
+
readonly canHighlight?: boolean;
|
|
104
|
+
readonly visible: boolean;
|
|
105
|
+
}
|
|
106
|
+
export interface CadBlockModel {
|
|
107
|
+
readonly usages: readonly CadBlockUsageRow[];
|
|
108
|
+
toggleInsert(insertId: string, visible?: boolean): void;
|
|
109
|
+
batchToggleInserts?(updates: ReadonlyArray<{
|
|
110
|
+
insertId: string;
|
|
111
|
+
visible: boolean;
|
|
112
|
+
}>): void;
|
|
113
|
+
}
|
|
114
|
+
export interface CadInsertSelectionId {
|
|
115
|
+
readonly kind: 'insert';
|
|
116
|
+
readonly layerIndex: number;
|
|
117
|
+
readonly variantId: number;
|
|
118
|
+
readonly instanceId: number;
|
|
119
|
+
}
|
|
120
|
+
export interface CadInsertSelection {
|
|
121
|
+
readonly documentKey: string | null;
|
|
122
|
+
readonly id: CadInsertSelectionId;
|
|
123
|
+
}
|
|
124
|
+
export interface CadTextSelectionId {
|
|
125
|
+
readonly kind: 'text';
|
|
126
|
+
readonly textId: number;
|
|
127
|
+
}
|
|
128
|
+
export interface CadTextSelection {
|
|
129
|
+
readonly documentKey: string | null;
|
|
130
|
+
readonly id: CadTextSelectionId;
|
|
131
|
+
}
|
|
132
|
+
export interface CadTextDetails {
|
|
133
|
+
readonly id: CadTextSelectionId;
|
|
134
|
+
readonly content: string;
|
|
135
|
+
readonly x: number;
|
|
136
|
+
readonly y: number;
|
|
137
|
+
readonly height: number;
|
|
138
|
+
readonly rotation: number;
|
|
139
|
+
readonly layerName: string;
|
|
140
|
+
readonly layerIndex: number;
|
|
141
|
+
}
|
|
142
|
+
export interface CadInsertDetails {
|
|
143
|
+
readonly id: CadInsertSelectionId;
|
|
144
|
+
readonly label: string;
|
|
145
|
+
readonly blockName: string;
|
|
146
|
+
readonly layerName: string;
|
|
147
|
+
readonly layerIndex: number;
|
|
148
|
+
readonly tx: number;
|
|
149
|
+
readonly ty: number;
|
|
150
|
+
readonly rotation: number | null;
|
|
151
|
+
readonly scaleX: number | null;
|
|
152
|
+
readonly scaleY: number | null;
|
|
153
|
+
readonly bbox: {
|
|
154
|
+
readonly minX: number;
|
|
155
|
+
readonly minY: number;
|
|
156
|
+
readonly maxX: number;
|
|
157
|
+
readonly maxY: number;
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
export interface CadInspectorModel {
|
|
161
|
+
readonly selection: CadInsertSelection | null;
|
|
162
|
+
readonly details: CadInsertDetails | null;
|
|
163
|
+
/** Optional so existing inspector consumers remain source-compatible. */
|
|
164
|
+
readonly textSelection?: CadTextSelection | null;
|
|
165
|
+
readonly textDetails?: CadTextDetails | null;
|
|
166
|
+
}
|
|
167
|
+
export interface CadScaleRulerState {
|
|
168
|
+
readonly visible: boolean;
|
|
169
|
+
readonly lengthLabel: string;
|
|
170
|
+
readonly worldLength: number;
|
|
171
|
+
}
|
|
172
|
+
export interface CadHudModel {
|
|
173
|
+
readonly filename: string | null;
|
|
174
|
+
readonly fileCount: number;
|
|
175
|
+
readonly visibleLayerCount: number;
|
|
176
|
+
readonly totalLayerCount: number;
|
|
177
|
+
readonly statusMessage: string;
|
|
178
|
+
readonly zoomLabel: string;
|
|
179
|
+
readonly orbitDistanceLabel: string;
|
|
180
|
+
readonly scaleRuler: CadScaleRulerState | null;
|
|
181
|
+
readonly viewportVertexCount: number;
|
|
182
|
+
readonly drawCalls: number;
|
|
183
|
+
readonly fps: number;
|
|
184
|
+
readonly lineRenderMode: string;
|
|
185
|
+
readonly entityCount: number;
|
|
186
|
+
readonly lineCount: number;
|
|
187
|
+
readonly fillCount: number;
|
|
188
|
+
readonly dotCount: number;
|
|
189
|
+
readonly textCount: number;
|
|
190
|
+
readonly renderableCount: number;
|
|
191
|
+
readonly submittedVertexRefs: number;
|
|
192
|
+
readonly blockVariantCount: number;
|
|
193
|
+
readonly blockInstanceCount: number;
|
|
194
|
+
readonly splitBlockLayerGroupCount: number;
|
|
195
|
+
readonly renderDebugBreakdown: readonly RenderDebugBreakdownEntry[];
|
|
196
|
+
readonly splitBlockLayerDetails: readonly SplitBlockLayerDetail[];
|
|
197
|
+
readonly phase: CadSessionPhase | null;
|
|
198
|
+
}
|
|
199
|
+
export interface CadViewerEventMap {
|
|
200
|
+
'document-change': {
|
|
201
|
+
document: CadDocumentHandle | null;
|
|
202
|
+
};
|
|
203
|
+
'layer-change': {
|
|
204
|
+
layers: CadLayerModel;
|
|
205
|
+
};
|
|
206
|
+
'block-change': {
|
|
207
|
+
blocks: CadBlockModel;
|
|
208
|
+
};
|
|
209
|
+
'inspector-change': {
|
|
210
|
+
inspector: CadInspectorModel;
|
|
211
|
+
};
|
|
212
|
+
'hud-change': {
|
|
213
|
+
hud: CadHudModel;
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
export interface CadViewerCapability {
|
|
217
|
+
readonly document: CadDocumentHandle | null;
|
|
218
|
+
readonly layers: CadLayerModel;
|
|
219
|
+
readonly blocks: CadBlockModel;
|
|
220
|
+
readonly inspector: CadInspectorModel;
|
|
221
|
+
readonly hud: CadHudModel;
|
|
222
|
+
open(source: CadLoadSource, options?: CadOpenOptions): Promise<CadDocumentHandle>;
|
|
223
|
+
close(): void;
|
|
224
|
+
selectInsert?(insertId: string | null): void;
|
|
225
|
+
renderInsertPreview(canvas: HTMLCanvasElement): boolean;
|
|
226
|
+
pickTextAtScreen?(clientX: number, clientY: number): {
|
|
227
|
+
selection: CadTextSelection;
|
|
228
|
+
details: CadTextDetails | null;
|
|
229
|
+
} | null;
|
|
230
|
+
setTextSelection?(selection: CadTextSelection | null, details: CadTextDetails | null): void;
|
|
231
|
+
on<K extends keyof CadViewerEventMap>(type: K, listener: (event: CadViewerEventMap[K]) => void): () => void;
|
|
232
|
+
}
|
|
233
|
+
export type ViewerUiPreset = 'cad-readonly';
|
|
234
|
+
export type ViewerUiTheme = 'dark' | 'light';
|
|
235
|
+
export interface ViewerUiParts {
|
|
236
|
+
layerPanel?: boolean;
|
|
237
|
+
propertyPanel?: boolean;
|
|
238
|
+
hud?: boolean;
|
|
239
|
+
viewMode?: boolean;
|
|
240
|
+
fit?: boolean;
|
|
241
|
+
scaleRuler?: boolean;
|
|
242
|
+
/** Show the line-render-mode chip in the infobar. Default: true. */
|
|
243
|
+
infobarLineMode?: boolean;
|
|
244
|
+
/** Show the session phase label in the infobar. Default: true. */
|
|
245
|
+
infobarPhase?: boolean;
|
|
246
|
+
/** Show the Debug details card in the infobar. Default: true. */
|
|
247
|
+
infobarDebug?: boolean;
|
|
248
|
+
}
|
|
249
|
+
export interface ViewerUiOptions {
|
|
250
|
+
root: HTMLElement;
|
|
251
|
+
preset?: ViewerUiPreset;
|
|
252
|
+
parts?: ViewerUiParts;
|
|
253
|
+
theme?: ViewerUiTheme;
|
|
254
|
+
}
|
|
255
|
+
export interface CameraStateStore {
|
|
256
|
+
read(key: string): Promise<unknown> | unknown;
|
|
257
|
+
write(key: string, value: unknown): Promise<void> | void;
|
|
258
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { createViewer } from './viewer';
|
|
2
|
-
export type { Viewer, ViewerEventMap, ViewerFitViewOptions, ViewerHighlightOptions, ViewerOptions, ViewerPickOptions, ViewerPickResult, ViewerViewMode, } from './types';
|
|
2
|
+
export type { CadBlockModel, CadDocumentHandle, CadFontResolver, CadResolvedTextFont, CadHudModel, CadInspectorModel, CadLayerModel, CadLoadSource, CadOpenOptions, CadTextDetails, CadTextSelection, CadTextSelectionId, CadViewerCapability, ResolveTextFont, CadViewerEventMap, CameraStateStore, Viewer, ViewerEventMap, ViewerEnvironment, ViewerFitViewOptions, ViewerHighlightOptions, ViewerOptions, ViewerPickOptions, ViewerPickResult, ViewerPointerEvent, ViewerUiOptions, ViewerUiParts, ViewerUiPreset, ViewerUiTheme, ViewerViewMode, } from './types';
|