@nebula-spatial/viewer 0.2.4 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/README.md +101 -2
- package/dist/cad/types.d.ts +134 -16
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2013 -1060
- package/dist/plugins.d.ts +131 -0
- package/dist/types.d.ts +59 -2
- package/package.json +2 -2
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { Box3, Object3D } from 'three';
|
|
2
|
+
import type { CadHit, CadSelection, CadViewerSnapshot, CadViewerEventMap } from './cad/types';
|
|
3
|
+
import type { ViewerEventMap, ViewerViewMode } from './types';
|
|
4
|
+
export interface Disposable {
|
|
5
|
+
dispose(): void;
|
|
6
|
+
}
|
|
7
|
+
export interface ToolbarItem {
|
|
8
|
+
readonly id: string;
|
|
9
|
+
readonly label: string;
|
|
10
|
+
readonly title?: string;
|
|
11
|
+
readonly disabled?: boolean;
|
|
12
|
+
readonly onClick: () => void;
|
|
13
|
+
}
|
|
14
|
+
export interface ViewerState {
|
|
15
|
+
readonly viewMode: ViewerViewMode;
|
|
16
|
+
readonly selectedObject: Object3D | null;
|
|
17
|
+
readonly highlightedObject: Object3D | null;
|
|
18
|
+
readonly isDisposed: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface ViewerPluginContext {
|
|
21
|
+
readonly cad: {
|
|
22
|
+
$read(): CadViewerSnapshot;
|
|
23
|
+
};
|
|
24
|
+
readonly viewer: {
|
|
25
|
+
$getState(): ViewerState;
|
|
26
|
+
};
|
|
27
|
+
readonly commands: {
|
|
28
|
+
setLayerVisible(index: number, visible: boolean): boolean;
|
|
29
|
+
setSelection(selection: CadSelection | null): void;
|
|
30
|
+
fitDocument(): boolean;
|
|
31
|
+
setViewMode(mode: ViewerViewMode): void;
|
|
32
|
+
};
|
|
33
|
+
readonly events: {
|
|
34
|
+
on<K extends keyof (ViewerEventMap & CadViewerEventMap)>(type: K, listener: (event: (ViewerEventMap & CadViewerEventMap)[K]) => void): () => void;
|
|
35
|
+
};
|
|
36
|
+
readonly layout: {
|
|
37
|
+
mount(node: Node, options?: {
|
|
38
|
+
position?: 'left' | 'right' | 'top' | 'bottom' | 'overlay';
|
|
39
|
+
}): Disposable;
|
|
40
|
+
onInsetsChange(listener: (insets: ViewerEventMap['ui-layout-change']['contentInsets']) => void): () => void;
|
|
41
|
+
};
|
|
42
|
+
contribute(point: ViewerContributionPoint): Disposable;
|
|
43
|
+
dispose(): void;
|
|
44
|
+
}
|
|
45
|
+
export interface ViewerInteractionHooks {
|
|
46
|
+
/** Return false to consume the interaction and stop the managed pipeline. */
|
|
47
|
+
onPick?: (hit: CadHit | null) => boolean | void;
|
|
48
|
+
onHover?: (hit: CadHit | null) => void;
|
|
49
|
+
onSelect?: (selection: CadSelection | null) => void;
|
|
50
|
+
onClear?: () => void;
|
|
51
|
+
}
|
|
52
|
+
export type ViewerContributionPoint = {
|
|
53
|
+
readonly kind: 'panel';
|
|
54
|
+
readonly id: string;
|
|
55
|
+
readonly factory: (ctx: ViewerPluginContext) => Node;
|
|
56
|
+
} | {
|
|
57
|
+
readonly kind: 'toolbar';
|
|
58
|
+
readonly id: string;
|
|
59
|
+
readonly items: readonly ToolbarItem[];
|
|
60
|
+
} | {
|
|
61
|
+
readonly kind: 'hud';
|
|
62
|
+
readonly id: string;
|
|
63
|
+
readonly factory: (ctx: ViewerPluginContext) => Node;
|
|
64
|
+
} | {
|
|
65
|
+
readonly kind: 'statusbar';
|
|
66
|
+
readonly id: string;
|
|
67
|
+
readonly factory: (ctx: ViewerPluginContext) => Node;
|
|
68
|
+
} | {
|
|
69
|
+
readonly kind: 'inspector';
|
|
70
|
+
readonly id: string;
|
|
71
|
+
readonly matcher: (selection: CadSelection) => boolean;
|
|
72
|
+
readonly render: (ctx: ViewerPluginContext, selection: CadSelection) => Node;
|
|
73
|
+
} | {
|
|
74
|
+
readonly kind: 'interaction';
|
|
75
|
+
readonly id: string;
|
|
76
|
+
readonly hooks: ViewerInteractionHooks;
|
|
77
|
+
} | {
|
|
78
|
+
readonly kind: 'command';
|
|
79
|
+
readonly id: string;
|
|
80
|
+
readonly handler: (ctx: ViewerPluginContext, args?: unknown) => void;
|
|
81
|
+
} | {
|
|
82
|
+
readonly kind: 'fit-policy';
|
|
83
|
+
readonly id: string;
|
|
84
|
+
readonly resolve: (ctx: ViewerPluginContext) => Box3 | null;
|
|
85
|
+
};
|
|
86
|
+
export interface ViewerPlugin {
|
|
87
|
+
readonly id: string;
|
|
88
|
+
activate(context: ViewerPluginContext): void | Promise<void>;
|
|
89
|
+
deactivate?(): void | Promise<void>;
|
|
90
|
+
}
|
|
91
|
+
type SnapshotReader = () => CadViewerSnapshot;
|
|
92
|
+
type StateReader = () => ViewerState;
|
|
93
|
+
type PluginEventMap = ViewerEventMap & CadViewerEventMap;
|
|
94
|
+
type EventSubscriber = <K extends keyof PluginEventMap>(type: K, listener: (event: PluginEventMap[K]) => void) => () => void;
|
|
95
|
+
type CommandApi = ViewerPluginContext['commands'];
|
|
96
|
+
export declare class ViewerPluginManager implements ViewerPluginRegistry {
|
|
97
|
+
private readonly readCad;
|
|
98
|
+
private readonly readState;
|
|
99
|
+
private readonly subscribe;
|
|
100
|
+
private readonly commands;
|
|
101
|
+
private readonly hostElement;
|
|
102
|
+
private readonly pluginsById;
|
|
103
|
+
private readonly contributions;
|
|
104
|
+
private readonly commandContributions;
|
|
105
|
+
private refreshingInspectors;
|
|
106
|
+
private disposed;
|
|
107
|
+
constructor(readCad: SnapshotReader, readState: StateReader, subscribe: EventSubscriber, commands: CommandApi, hostElement: HTMLElement);
|
|
108
|
+
register(plugin: ViewerPlugin): Disposable;
|
|
109
|
+
use(plugins: readonly ViewerPlugin[], options?: {
|
|
110
|
+
replace?: boolean;
|
|
111
|
+
}): void;
|
|
112
|
+
private deactivate;
|
|
113
|
+
disposeAll(): void;
|
|
114
|
+
dispose(): void;
|
|
115
|
+
dispatchInteraction(kind: keyof ViewerInteractionHooks, value: CadHit | CadSelection | null): boolean;
|
|
116
|
+
findFitPolicy(): Box3 | null;
|
|
117
|
+
executeCommand(id: string, args?: unknown): boolean;
|
|
118
|
+
hasCommand(id: string): boolean;
|
|
119
|
+
private removeContribution;
|
|
120
|
+
private mountContribution;
|
|
121
|
+
private isFirstMatchingInspector;
|
|
122
|
+
private refreshInspectorContributions;
|
|
123
|
+
private assertActive;
|
|
124
|
+
}
|
|
125
|
+
export interface ViewerPluginRegistry {
|
|
126
|
+
register(plugin: ViewerPlugin): Disposable;
|
|
127
|
+
use(plugins: readonly ViewerPlugin[], options?: {
|
|
128
|
+
replace?: boolean;
|
|
129
|
+
}): void;
|
|
130
|
+
}
|
|
131
|
+
export {};
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { Box3, ColorRepresentation, Object3D, Vector3 } from 'three';
|
|
2
2
|
import type { CadViewerCapability, CameraStateStore, ViewerUiOptions } from './cad/types';
|
|
3
|
-
export type { CadBlockModel, CadDocumentHandle, CadFontResolver, CadResolvedTextFont, CadHudModel, CadInspectorModel, CadLayerModel,
|
|
3
|
+
export type { CadBlockModel, CadDocumentHandle, CadDocumentUnits, CadFontResolver, CadFontRequest, CadResolvedFont, CadResolvedTextFont, CadTextWarmupOptions, CadHudModel, CadHudSnapshot, CadInspectorModel, CadInspectorSnapshot, CadLayerModel, CadLayerRow, CadBlockUsageRow, CadSessionPhase, CadWorldBounds, CadScaleRulerState, CadInsertDetails, CadInsertSelection, CadInsertSelectionId, CadTextDetails, CadTextSelection, CadTextSelectionId, CadSelection, CadHit, CadViewerSnapshot, CadLoadProgress, CadViewerErrorCode, CadViewerErrorEvent, CadLoadSource, CadOpenOptions, CadSessionLoadTiming, RenderDebugBreakdownEntry, SplitBlockLayerDetail, CadViewerCapability, ResolveTextFont, CadViewerEventMap, CameraStateStore, ViewerUiKeyboardOptions, ViewerUiOptions, ViewerUiParts, ViewerUiPreset, ViewerUiStateStore, ViewerUiTheme, ViewerUiTokens, } from './cad/types';
|
|
4
4
|
export type ViewerViewMode = '2d' | '3d';
|
|
5
|
+
export type CadInteractionMode = 'managed' | 'manual' | 'disabled';
|
|
6
|
+
export type CameraChangeReason = 'pointer' | 'wheel' | 'fit' | 'restore' | 'api' | 'view-mode';
|
|
5
7
|
export type ViewerEnvironment = 'room' | {
|
|
6
8
|
/** Load an external equirectangular HDR texture for image-based lighting. */
|
|
7
9
|
readonly type: 'hdr';
|
|
@@ -50,6 +52,22 @@ export interface ViewerOptions {
|
|
|
50
52
|
environment?: ViewerEnvironment;
|
|
51
53
|
autoSelectOnPick?: boolean;
|
|
52
54
|
pointerPick?: boolean;
|
|
55
|
+
/** CAD click policy. Defaults to managed. */
|
|
56
|
+
cadInteraction?: CadInteractionMode;
|
|
57
|
+
cadInteractionStyle?: {
|
|
58
|
+
hover?: {
|
|
59
|
+
color?: ColorRepresentation;
|
|
60
|
+
fillOpacity?: number;
|
|
61
|
+
edgeOpacity?: number;
|
|
62
|
+
enabled?: boolean;
|
|
63
|
+
};
|
|
64
|
+
selected?: {
|
|
65
|
+
color?: ColorRepresentation;
|
|
66
|
+
fillOpacity?: number;
|
|
67
|
+
edgeOpacity?: number;
|
|
68
|
+
enabled?: boolean;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
53
71
|
cameraStateStore?: CameraStateStore | false;
|
|
54
72
|
/** Max delay for merged viewport demands while the interaction is active. Default 160ms. */
|
|
55
73
|
viewportDemandCoalesceMs?: number;
|
|
@@ -75,6 +93,10 @@ export interface ViewerPickResult {
|
|
|
75
93
|
export interface ViewerHighlightOptions {
|
|
76
94
|
color?: ColorRepresentation;
|
|
77
95
|
}
|
|
96
|
+
export interface ViewerObjectOptions {
|
|
97
|
+
/** Viewer only mounts the object; the caller retains responsibility for GPU resource disposal. */
|
|
98
|
+
readonly ownership?: 'borrowed';
|
|
99
|
+
}
|
|
78
100
|
export interface ViewerRenderStats {
|
|
79
101
|
readonly drawCalls: number;
|
|
80
102
|
readonly submittedVertexRefs: number;
|
|
@@ -121,6 +143,18 @@ export interface ViewerEventMap {
|
|
|
121
143
|
};
|
|
122
144
|
'camera-change': {
|
|
123
145
|
viewMode: ViewerViewMode;
|
|
146
|
+
reason: CameraChangeReason;
|
|
147
|
+
interaction: 'active' | 'idle';
|
|
148
|
+
};
|
|
149
|
+
'ui-layout-change': {
|
|
150
|
+
contentInsets: {
|
|
151
|
+
readonly top: number;
|
|
152
|
+
readonly right: number;
|
|
153
|
+
readonly bottom: number;
|
|
154
|
+
readonly left: number;
|
|
155
|
+
};
|
|
156
|
+
layerPanelOpen: boolean;
|
|
157
|
+
propertyPanelOpen: boolean;
|
|
124
158
|
};
|
|
125
159
|
}
|
|
126
160
|
export interface Viewer {
|
|
@@ -131,13 +165,33 @@ export interface Viewer {
|
|
|
131
165
|
readonly highlightedObject: Object3D | null;
|
|
132
166
|
readonly isDisposed: boolean;
|
|
133
167
|
readonly cad: CadViewerCapability;
|
|
134
|
-
|
|
168
|
+
readonly overlays: {
|
|
169
|
+
set(key: string, object: Object3D, options?: {
|
|
170
|
+
owned?: boolean;
|
|
171
|
+
}): void;
|
|
172
|
+
remove(key: string, options?: {
|
|
173
|
+
dispose?: boolean;
|
|
174
|
+
}): Object3D | null;
|
|
175
|
+
};
|
|
176
|
+
readonly camera: {
|
|
177
|
+
getState(): ViewerCameraSnapshot | null;
|
|
178
|
+
/** Applies a validated snapshot immediately. Animated transitions are not part of the current contract. */
|
|
179
|
+
setState(snapshot: ViewerCameraSnapshot): boolean;
|
|
180
|
+
reset(): boolean;
|
|
181
|
+
};
|
|
182
|
+
readonly plugins: import('./plugins').ViewerPluginRegistry;
|
|
183
|
+
readonly commands: {
|
|
184
|
+
execute(id: string, args?: unknown): boolean;
|
|
185
|
+
has(id: string): boolean;
|
|
186
|
+
};
|
|
187
|
+
addObject(object: Object3D, options?: ViewerObjectOptions): void;
|
|
135
188
|
removeObject(object: Object3D): boolean;
|
|
136
189
|
setVisible(object: Object3D, visible: boolean): void;
|
|
137
190
|
setViewMode(mode: ViewerViewMode, options?: {
|
|
138
191
|
preserveOrbit?: boolean;
|
|
139
192
|
}): void;
|
|
140
193
|
fitView(target?: Object3D | Box3, options?: ViewerFitViewOptions): boolean;
|
|
194
|
+
fitAll(options?: ViewerFitViewOptions): boolean;
|
|
141
195
|
screenToWorldOnPlane(clientX: number, clientY: number, planeZ?: number): Vector3 | null;
|
|
142
196
|
pick(clientX: number, clientY: number, options?: ViewerPickOptions): ViewerPickResult | null;
|
|
143
197
|
setSelection(object: Object3D | null): void;
|
|
@@ -146,4 +200,7 @@ export interface Viewer {
|
|
|
146
200
|
resize(): boolean;
|
|
147
201
|
requestRender(): void;
|
|
148
202
|
dispose(): void;
|
|
203
|
+
use(plugins: readonly import('./plugins').ViewerPlugin[], options?: {
|
|
204
|
+
replace?: boolean;
|
|
205
|
+
}): void;
|
|
149
206
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebula-spatial/viewer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Read-only Three.js viewer facade",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"engines": {
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"prepack": "npm run build"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@nebula-spatial/cad-loader": "^0.
|
|
39
|
+
"@nebula-spatial/cad-loader": "^0.3.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"three": "0.182.0"
|