@cognite/reveal-widget 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # @cognite/reveal-widget
2
+
3
+ A React component for embedding an interactive [Cognite Reveal](https://cognitedata.github.io/reveal)
4
+ 3D viewer in your application: `RevealWidget`. It loads and renders CAD models, point clouds,
5
+ 360° image collections, and CDF scenes, and lets you highlight and focus specific instances
6
+ (assets) within them.
7
+
8
+ This package exposes `RevealWidget` and the types needed to drive it via
9
+ `RevealWidgetController`. More capabilities from the broader Reveal React Components toolkit
10
+ will be exposed here incrementally over time.
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install @cognite/reveal-widget @cognite/reveal @cognite/sdk react react-dom
16
+ ```
17
+
18
+ `react`, `react-dom`, `@cognite/reveal`, and `@cognite/sdk` are peer dependencies — install
19
+ versions matching what your app already uses. Everything else the widget needs installs
20
+ automatically as a regular dependency.
21
+
22
+ If your bundler doesn't already dedupe singletons across your dependency tree, add:
23
+
24
+ ```ts
25
+ // vite.config.ts
26
+ resolve: { dedupe: ['three', '@cognite/reveal'] }
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ `RevealWidget` hands you a `RevealWidgetController` via `setControllerRef`. Rather than
32
+ reacting to prop changes through `useEffect`, wrap it in your own class and drive it
33
+ imperatively — e.g. from event handlers elsewhere in your app (a click on an asset in a list,
34
+ a button press, etc.):
35
+
36
+ ```tsx
37
+ import { useRef } from 'react';
38
+ import type { CogniteClient } from '@cognite/sdk';
39
+ import {
40
+ Default3DStyles,
41
+ RevealWidget,
42
+ type Reveal3DResourceHandle,
43
+ type RevealWidgetController,
44
+ type ThreeDResourceIdentifier,
45
+ type InstanceId,
46
+ } from '@cognite/reveal-widget';
47
+
48
+ class ThreeDViewerController {
49
+ private model: Reveal3DResourceHandle | undefined;
50
+
51
+ constructor(private readonly widgetController: RevealWidgetController) {}
52
+
53
+ async loadModel(resource: ThreeDResourceIdentifier): Promise<void> {
54
+ this.model = await this.widgetController.addResource(resource);
55
+ this.widgetController.cameraController.focusModel(this.model);
56
+ }
57
+
58
+ async highlightAsset(instanceId: InstanceId): Promise<void> {
59
+ if (this.model === undefined) return;
60
+ await this.widgetController.styleByInstance(
61
+ [{ instanceIds: [instanceId], style: Default3DStyles.Highlighted }],
62
+ [this.model]
63
+ );
64
+ await this.widgetController.focusInstances([instanceId]);
65
+ }
66
+
67
+ dispose(): void {
68
+ this.model?.remove();
69
+ }
70
+ }
71
+
72
+ export function ThreeDViewer({
73
+ sdk,
74
+ resource,
75
+ onReady,
76
+ }: {
77
+ sdk: CogniteClient;
78
+ resource: ThreeDResourceIdentifier;
79
+ onReady: (viewer: ThreeDViewerController | undefined) => void;
80
+ }) {
81
+ const viewerRef = useRef<ThreeDViewerController>();
82
+
83
+ function handleWidgetController(widgetController: RevealWidgetController | undefined) {
84
+ viewerRef.current?.dispose();
85
+
86
+ if (widgetController === undefined) {
87
+ viewerRef.current = undefined;
88
+ onReady(undefined);
89
+ return;
90
+ }
91
+
92
+ const viewer = new ThreeDViewerController(widgetController);
93
+ void viewer.loadModel(resource);
94
+ viewerRef.current = viewer;
95
+ onReady(viewer);
96
+ }
97
+
98
+ return (
99
+ <div style={{ width: '100%', height: '70vh', position: 'relative' }}>
100
+ <RevealWidget
101
+ viewerOptions={{ sdk, useCoreDm: true }}
102
+ setControllerRef={handleWidgetController}
103
+ />
104
+ </div>
105
+ );
106
+ }
107
+
108
+ // Elsewhere, e.g. from a click handler in whatever renders a list of assets:
109
+ // viewer.highlightAsset({ externalId: 'CogniteAsset-1022', space: 'my-space' });
110
+ ```
111
+
112
+ `RevealWidget` wraps its own Reveal context internally — don't wrap it in another provider from
113
+ this package.
114
+
115
+ ### Loading resources
116
+
117
+ `controller.addResource(...)` accepts CAD models, point clouds, 360° image collections, or
118
+ scenes, identified by `type` and `sourceType`:
119
+
120
+ ```ts
121
+ { type: 'cad', sourceType: 'classic', modelId: number, revisionId: number }
122
+ { type: 'cad', sourceType: 'cdm', externalId: string, space: string }
123
+ { type: 'pointcloud', sourceType: 'classic', modelId: number, revisionId: number }
124
+ { type: 'pointcloud', sourceType: 'cdm', externalId: string, space: string }
125
+ { type: 'image360', sourceType: 'dm' | 'cdm', externalId: string, space: string }
126
+ { type: 'image360', sourceType: 'events', siteId: string }
127
+ { type: 'scene', externalId: string, space: string }
128
+ ```
129
+
130
+ CAD/point cloud/image360 resources resolve to a `Reveal3DResourceHandle` usable with
131
+ `styleByInstance`/`getModels()`/`cameraController.focusModel()`; a `'scene'` resource resolves to
132
+ a handle that only supports `.remove()`.
133
+
134
+ ### Highlighting instances
135
+
136
+ Instances (assets) are identified either by classic numeric asset ID or by a data modeling
137
+ `{ externalId, space }` reference:
138
+
139
+ ```ts
140
+ instanceIds: [1560727417020285]
141
+ instanceIds: [{ externalId: 'CogniteAsset-1022', space: 'my-space' }]
142
+ ```
143
+
144
+ ### Camera control
145
+
146
+ ```ts
147
+ controller.cameraController.focusModel(handle); // fit one model
148
+ controller.cameraController.focusCameraAll(); // fit all models
149
+ await controller.focusInstances([someInstanceId]); // zoom to a specific instance
150
+ ```
151
+
152
+ ## Cleaning up
153
+
154
+ Resources added via `addResource` should be removed when no longer needed:
155
+
156
+ ```ts
157
+ const handle = await controller.addResource(resource);
158
+ // ...later:
159
+ handle.remove();
160
+ ```
@@ -0,0 +1,252 @@
1
+ import { CameraState } from '@cognite/reveal';
2
+ import { Cognite3DViewerOptions } from '@cognite/reveal';
3
+ import { Image360AnnotationAppearance } from '@cognite/reveal';
4
+ import type { IndexSet } from '@cognite/reveal';
5
+ import type { Matrix4 } from 'three';
6
+ import { NodeAppearance } from '@cognite/reveal';
7
+ import { PropsWithChildren } from 'react';
8
+ import { ReactElement } from 'react';
9
+
10
+ export declare type AddReveal3DResource =
11
+ | CadAddOptions
12
+ | PointCloudAddOptions
13
+ | Image360AddOptions;
14
+
15
+ export declare type AllResourceIdentifier =
16
+ | ThreeDResourceIdentifier
17
+ | SceneResourceIdentifier;
18
+
19
+ export declare type AssetId = number;
20
+
21
+ export declare type BaseAddOptions = {
22
+ transform?: Matrix4;
23
+ defaultVisible?: boolean;
24
+ };
25
+
26
+ export declare type CadAddOptions = BaseAddOptions &
27
+ (Classic3DResourceIdentifier | DM3DResourceIdentifier) & {
28
+ styling?: CadModelStyling;
29
+ modelCategory: 'model3d';
30
+ };
31
+
32
+ export declare type CadModelStyling = {
33
+ default?: NodeAppearance;
34
+ mapped?: NodeAppearance;
35
+ nodeGroups?: TreeIndexStylingGroup[];
36
+ };
37
+
38
+ export declare type CadResourceIdentifier = (
39
+ | Classic3DResourceIdentifier
40
+ | DM3DResourceIdentifier
41
+ ) & { type: 'cad' };
42
+
43
+ export declare type Classic3DResourceIdentifier = {
44
+ readonly sourceType: 'classic';
45
+ readonly modelId: number;
46
+ readonly revisionId: number;
47
+ };
48
+
49
+ /**
50
+ * Public API surface for the standalone `@cognite/reveal-widget` npm package.
51
+ *
52
+ * `RevealWidget` here is the real, unmodified implementation from
53
+ * `@cognite/reveal-react-components` — there is no runtime wrapper. The resource/identifier
54
+ * types above are re-exported directly from `@cognite/reveal-react-components`'s narrow,
55
+ * already-subpath-exported type barrels (`./data-providers/types`, `./utilities/modelIds`,
56
+ * `./utilities`). `vite.config.ts` sets `bundledPackages: ['@cognite/reveal-react-components']`
57
+ * on the `dts` plugin, which tells API Extractor (used internally for `rollupTypes`) to inline
58
+ * these types' real declarations into `dist/index.d.ts` instead of leaving a bare
59
+ * `import ... from '@cognite/reveal-react-components/...'` that an external consumer couldn't
60
+ * resolve (that package is `private: true` and never published).
61
+ *
62
+ * `Reveal3DResourceHandle`, `RevealWidgetController`, `RevealWidgetCameraController`, and
63
+ * `RevealWidgetProps` below are still hand-declared, because their real counterparts (only
64
+ * reachable via the entangled `./ui/components` export) expose `RevealDomainObject`/
65
+ * `SceneDomainObject` directly in their signatures — too large for API Extractor's type bundler
66
+ * and not meaningful for an external consumer anyway. `src/index.test.ts` has compile-time-only
67
+ * (`// @ts-expect-error`-driven) tests asserting these hand-written types stay structurally
68
+ * compatible with the real implementation — update both together when the real API changes.
69
+ */
70
+ export declare const Default3DStyles: {
71
+ Highlighted: {
72
+ cad: NodeAppearance;
73
+ pointcloud: NodeAppearance;
74
+ image360: NodeAppearance;
75
+ };
76
+ };
77
+
78
+ export declare type DM3DResourceIdentifier = {
79
+ readonly sourceType: 'cdm';
80
+ readonly externalId: string;
81
+ readonly space: string;
82
+ };
83
+
84
+ export declare type DmsUniqueIdentifier = {
85
+ space: Space;
86
+ externalId: ExternalId;
87
+ };
88
+
89
+ export declare type ExternalId = string;
90
+
91
+ export declare type Image360AddOptions = BaseAddOptions &
92
+ (Image360EventsResourceIdentifier | Image360DMResourceIdentifier) & {
93
+ iconCullingOptions?: Image360IconCullingOptions;
94
+ modelCategory: 'image360';
95
+ };
96
+
97
+ export declare type Image360DMResourceIdentifier = {
98
+ readonly sourceType: 'dm' | 'cdm';
99
+ readonly externalId: string;
100
+ readonly space: string;
101
+ };
102
+
103
+ export declare type Image360EventsResourceIdentifier = {
104
+ readonly sourceType: 'events';
105
+ readonly siteId: string;
106
+ };
107
+
108
+ export declare type Image360IconCullingOptions = {
109
+ radius?: number;
110
+ iconCountLimit?: number;
111
+ };
112
+
113
+ export declare type Image360ResourceIdentifier = (
114
+ | Image360DMResourceIdentifier
115
+ | Image360EventsResourceIdentifier
116
+ ) & { type: 'image360' };
117
+
118
+ export declare type InstanceId = AssetId | DmsUniqueIdentifier;
119
+
120
+ export declare type InstanceStylingGroup = {
121
+ instanceIds: (DmsUniqueIdentifier | AssetId)[];
122
+ style: {
123
+ cad?: NodeAppearance;
124
+ pointcloud?: NodeAppearance;
125
+ image360?: Image360AnnotationAppearance;
126
+ };
127
+ };
128
+
129
+ export declare type PointCloudAddOptions = BaseAddOptions &
130
+ (Classic3DResourceIdentifier | DM3DResourceIdentifier) & {
131
+ styling?: {
132
+ default?: NodeAppearance;
133
+ mapped?: NodeAppearance;
134
+ };
135
+ modelCategory: 'model3d';
136
+ };
137
+
138
+ export declare type PointCloudResourceIdentifier = (
139
+ | Classic3DResourceIdentifier
140
+ | DM3DResourceIdentifier
141
+ ) & { type: 'pointcloud' };
142
+
143
+ /**
144
+ * A narrow, external-facing view of a loaded 3D resource (CAD model, point cloud, image360
145
+ * collection, or scene). This is a type-only narrowing — the actual object returned at runtime
146
+ * by `addResource()`/`getModels()` is still the real `RevealDomainObject`/`SceneDomainObject`.
147
+ * Only `.remove()` is published here to keep the exported type surface minimal.
148
+ */
149
+ export declare type Reveal3DResourceHandle = {
150
+ remove(): boolean;
151
+ };
152
+
153
+ export declare const RevealWidget: (props: PropsWithChildren<RevealWidgetProps>) => ReactElement;
154
+
155
+ export declare type RevealWidgetCameraController = {
156
+ /**
157
+ * Focus all visible models in the scene
158
+ */
159
+ focusCameraAll(): void;
160
+ /**
161
+ * Focus on a single given 3D model
162
+ */
163
+ focusModel(handle: Reveal3DResourceHandle): void;
164
+ /**
165
+ * Returns the state of the camera in the Reveal viewer
166
+ */
167
+ getCameraState(): Required<CameraState>;
168
+ /**
169
+ * Sets the state of the camera
170
+ */
171
+ setCameraState(cameraState: CameraState): void;
172
+ enterNearby360Image(): Promise<void> | undefined;
173
+ };
174
+
175
+ export declare type RevealWidgetController = {
176
+ /**
177
+ * Access the RevealWidgetCameraController for camera controls
178
+ */
179
+ readonly cameraController: RevealWidgetCameraController;
180
+ /**
181
+ * Add a 3D resource (i.e. model or scene) to the widget.
182
+ * Added resources can be removed by calling their `.remove` method.
183
+ */
184
+ addResource(resource: AllResourceIdentifier): Promise<Reveal3DResourceHandle>;
185
+ /**
186
+ * Get all models added to the RevealWidget
187
+ */
188
+ getModels(): Reveal3DResourceHandle[];
189
+ /**
190
+ * Get all models added to the RevealWidget that are visible
191
+ */
192
+ getVisibleModels(): Reveal3DResourceHandle[];
193
+ /**
194
+ * Style the provided instances with the associated styles in the given models, if
195
+ * the instances are contextualized to the models
196
+ */
197
+ styleByInstance(instanceStylingGroups: InstanceStylingGroup[], handles: Reveal3DResourceHandle[]): Promise<void>;
198
+ /**
199
+ * Moves the camera to show the provided instances in the visible models in the scene.
200
+ */
201
+ focusInstances(instances: InstanceId[]): Promise<void>;
202
+ };
203
+
204
+ export declare type RevealWidgetProps = {
205
+ /**
206
+ * Defines the initialization options for the RevealWidget, including the SDK and data modeling status
207
+ * The user can either specify these separately, or opt for the object
208
+ * `{ inheritFromRevealContext: true }`, in which case the Widget will assume the existence of
209
+ * a `RevealContext` mounted above it in the hierarchy.
210
+ */
211
+ viewerOptions: (Pick<Cognite3DViewerOptions, 'sdk' | 'onLoading'> & {
212
+ useCoreDm: boolean;
213
+ }) | {
214
+ /**
215
+ * Disables the RevealWidget's own RevealContext, relying on one defined in the application
216
+ * layer instead.
217
+ */
218
+ inheritFromRevealContext: true;
219
+ };
220
+ /**
221
+ * The widget uses this to set a reference to the widget controller.
222
+ * The widget calls this with `undefined` when the component unmounts or this callback changes
223
+ */
224
+ setControllerRef?: (controller: RevealWidgetController | undefined) => void;
225
+ };
226
+
227
+ export declare type SceneAddOptions = {
228
+ sourceType: 'dm';
229
+ externalId: string;
230
+ space: string;
231
+ modelCategory: 'scene';
232
+ };
233
+
234
+ export declare type SceneResourceIdentifier = {
235
+ type: 'scene';
236
+ externalId: string;
237
+ space: string;
238
+ };
239
+
240
+ export declare type Space = string;
241
+
242
+ export declare type ThreeDResourceIdentifier =
243
+ | CadResourceIdentifier
244
+ | PointCloudResourceIdentifier
245
+ | Image360ResourceIdentifier;
246
+
247
+ export declare type TreeIndexStylingGroup = {
248
+ treeIndexSet: IndexSet;
249
+ style: NodeAppearance;
250
+ };
251
+
252
+ export { }