@niivue/nv-web-component 1.0.0-rc.10
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 +226 -0
- package/dist/layouts.d.ts +20 -0
- package/dist/niivue-web-component.d.ts +107 -0
- package/dist/nv-web-component.js +1363 -0
- package/dist/nvscene-controller.d.ts +140 -0
- package/dist/types.d.ts +19 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# @niivue/nv-web-component
|
|
2
|
+
|
|
3
|
+
Lit-based Web Components for NiiVue. The package registers standard custom elements that work with plain HTML, Vite, Lit, React, Vue, Svelte, or any other browser environment that supports Web Components.
|
|
4
|
+
|
|
5
|
+
The API is DOM-first: configure elements with properties, call methods on the element instance, and listen for `CustomEvent`s.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
bun add @niivue/nv-web-component @niivue/niivue lit
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Getting started: single viewer
|
|
14
|
+
|
|
15
|
+
Importing the package registers `<niivue-viewer>` automatically.
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<niivue-viewer id="viewer" style="height: 600px"></niivue-viewer>
|
|
19
|
+
|
|
20
|
+
<script type="module">
|
|
21
|
+
import '@niivue/nv-web-component'
|
|
22
|
+
|
|
23
|
+
await customElements.whenDefined('niivue-viewer')
|
|
24
|
+
|
|
25
|
+
const viewer = document.querySelector('#viewer')
|
|
26
|
+
|
|
27
|
+
viewer.volumes = [
|
|
28
|
+
{
|
|
29
|
+
url: '/volumes/mni152.nii.gz',
|
|
30
|
+
name: 'MNI152',
|
|
31
|
+
colormap: 'gray',
|
|
32
|
+
},
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
viewer.addEventListener('image-loaded', (event) => {
|
|
36
|
+
console.log('loaded volume', event.detail)
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
viewer.addEventListener('location-change', (event) => {
|
|
40
|
+
console.log('location', event.detail)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
viewer.addEventListener('niivue-error', (event) => {
|
|
44
|
+
console.error('NiiVue error', event.detail)
|
|
45
|
+
})
|
|
46
|
+
</script>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Updating viewer settings
|
|
50
|
+
|
|
51
|
+
Use element methods for common NiiVue operations. The standalone viewer methods target its own NiiVue instance.
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
const viewer = document.querySelector('niivue-viewer')
|
|
55
|
+
|
|
56
|
+
await viewer.setColormap(0, 'hot')
|
|
57
|
+
await viewer.setOpacity(0, 0.8)
|
|
58
|
+
await viewer.setCalMinMax(0, 10, 200)
|
|
59
|
+
|
|
60
|
+
viewer.setColorbarVisible(true)
|
|
61
|
+
viewer.setCrosshairVisible(false)
|
|
62
|
+
viewer.setPrimaryDragMode(DRAG_MODE.pan)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
With imports:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
import { DRAG_MODE } from '@niivue/nv-web-component'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Getting started: scene of viewers
|
|
72
|
+
|
|
73
|
+
Use `<niivue-scene>` when you want multiple independent NiiVue viewers managed as one scene. The `layout` property controls how many viewer slots exist.
|
|
74
|
+
|
|
75
|
+
```html
|
|
76
|
+
<niivue-scene id="scene" layout="2x2" style="height: 600px"></niivue-scene>
|
|
77
|
+
|
|
78
|
+
<script type="module">
|
|
79
|
+
import '@niivue/nv-web-component'
|
|
80
|
+
|
|
81
|
+
await customElements.whenDefined('niivue-scene')
|
|
82
|
+
|
|
83
|
+
const scene = document.querySelector('#scene')
|
|
84
|
+
await scene.updateComplete
|
|
85
|
+
|
|
86
|
+
const volume = {
|
|
87
|
+
url: '/volumes/mni152.nii.gz',
|
|
88
|
+
name: 'MNI152',
|
|
89
|
+
colormap: 'gray',
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// The 2x2 layout creates four viewer slots. Load the same image into each
|
|
93
|
+
// viewer as separate NiiVue volume instances.
|
|
94
|
+
await Promise.all(
|
|
95
|
+
Array.from({ length: scene.snapshot.viewerCount }, (_value, index) =>
|
|
96
|
+
scene.loadVolume(index, volume),
|
|
97
|
+
),
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
scene.addEventListener('scene-change', (event) => {
|
|
101
|
+
console.log('scene snapshot', event.detail)
|
|
102
|
+
})
|
|
103
|
+
</script>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`customElements.whenDefined()` waits for element registration. Wait for Lit's
|
|
107
|
+
`scene.updateComplete`, or for the first `scene-change` event, before reading
|
|
108
|
+
`scene.snapshot.viewerCount` or loading volumes into scene viewers.
|
|
109
|
+
|
|
110
|
+
### Updating all scene viewers
|
|
111
|
+
|
|
112
|
+
Scene methods that target volumes take both a viewer index and a volume index. Batch operations across viewers with `Promise.all`.
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
const scene = document.querySelector('niivue-scene')
|
|
116
|
+
|
|
117
|
+
await Promise.all(
|
|
118
|
+
Array.from({ length: scene.snapshot.viewerCount }, (_value, index) =>
|
|
119
|
+
scene.setColormap(index, 0, 'hot'),
|
|
120
|
+
),
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Viewer-wide scene settings accept an optional `viewerIndex`. If omitted, they apply to every viewer in the scene.
|
|
125
|
+
|
|
126
|
+
```js
|
|
127
|
+
import { DRAG_MODE } from '@niivue/nv-web-component'
|
|
128
|
+
|
|
129
|
+
scene.setColorbarVisible(true)
|
|
130
|
+
scene.setCrosshairVisible(false)
|
|
131
|
+
scene.setPrimaryDragMode(DRAG_MODE.pan)
|
|
132
|
+
|
|
133
|
+
// Apply only to viewer 0.
|
|
134
|
+
scene.setCrosshairVisible(true, 0)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Changing layouts and broadcasting
|
|
138
|
+
|
|
139
|
+
```js
|
|
140
|
+
scene.layout = '1x2'
|
|
141
|
+
scene.broadcasting = true
|
|
142
|
+
|
|
143
|
+
scene.addEventListener('location-change', (event) => {
|
|
144
|
+
const { viewerIndex, data } = event.detail
|
|
145
|
+
console.log(`viewer ${viewerIndex}`, data)
|
|
146
|
+
})
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## API reference
|
|
150
|
+
|
|
151
|
+
### `<niivue-viewer>`
|
|
152
|
+
|
|
153
|
+
Properties:
|
|
154
|
+
|
|
155
|
+
- `volumes: ImageFromUrlOptions[]` - declarative volume list, diffed automatically.
|
|
156
|
+
- `options: Partial<NiiVueOptions>` - NiiVue construction options.
|
|
157
|
+
- `sliceType: number` / `slice-type` attribute - active slice type.
|
|
158
|
+
- `nv: NiiVue | null` - raw NiiVue instance after initialization.
|
|
159
|
+
|
|
160
|
+
Methods:
|
|
161
|
+
|
|
162
|
+
- `setColormap(volumeIndex, colormap)`
|
|
163
|
+
- `setOpacity(volumeIndex, opacity)`
|
|
164
|
+
- `setCalMinMax(volumeIndex, calMin, calMax)`
|
|
165
|
+
- `setColorbarVisible(visible)`
|
|
166
|
+
- `setCrosshairVisible(visible)`
|
|
167
|
+
- `setPrimaryDragMode(mode)`
|
|
168
|
+
- `setSecondaryDragMode(mode)`
|
|
169
|
+
|
|
170
|
+
Events:
|
|
171
|
+
|
|
172
|
+
- `location-change`
|
|
173
|
+
- `image-loaded`
|
|
174
|
+
- `niivue-error`
|
|
175
|
+
|
|
176
|
+
### `<niivue-scene>`
|
|
177
|
+
|
|
178
|
+
Properties:
|
|
179
|
+
|
|
180
|
+
- `layout: string` - one of the exported `defaultLayouts` keys (`1x1`, `1x2`, `2x1`, `1x3`, `3x1`, `2x2`, `3x3`).
|
|
181
|
+
- `broadcasting: boolean` - synchronizes crosshair/camera interactions across viewers.
|
|
182
|
+
- `snapshot: NvSceneControllerSnapshot` - current scene state.
|
|
183
|
+
- `scene: NvSceneController` - controller for advanced usage.
|
|
184
|
+
|
|
185
|
+
Methods:
|
|
186
|
+
|
|
187
|
+
- `addViewer(options?)`
|
|
188
|
+
- `removeViewer(index)`
|
|
189
|
+
- `canAddViewer()`
|
|
190
|
+
- `setViewerSliceLayout(index, layout)`
|
|
191
|
+
- `loadVolume(index, opts)`
|
|
192
|
+
- `loadVolumes(index, optsArray)`
|
|
193
|
+
- `removeVolume(index, url)`
|
|
194
|
+
- `setColormap(viewerIndex, volumeIndex, colormap)`
|
|
195
|
+
- `setOpacity(viewerIndex, volumeIndex, opacity)`
|
|
196
|
+
- `setCalMinMax(viewerIndex, volumeIndex, calMin, calMax)`
|
|
197
|
+
- `setColorbarVisible(visible, viewerIndex?)`
|
|
198
|
+
- `setCrosshairVisible(visible, viewerIndex?)`
|
|
199
|
+
- `setPrimaryDragMode(mode, viewerIndex?)`
|
|
200
|
+
- `setSecondaryDragMode(mode, viewerIndex?)`
|
|
201
|
+
|
|
202
|
+
Events:
|
|
203
|
+
|
|
204
|
+
- `scene-change`
|
|
205
|
+
- `viewer-created`
|
|
206
|
+
- `viewer-removed`
|
|
207
|
+
- `location-change`
|
|
208
|
+
- `image-loaded`
|
|
209
|
+
- `niivue-error`
|
|
210
|
+
- `volume-added`
|
|
211
|
+
- `volume-removed`
|
|
212
|
+
|
|
213
|
+
## Manual registration
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
import { defineNiivueWebComponents } from '@niivue/nv-web-component'
|
|
217
|
+
|
|
218
|
+
defineNiivueWebComponents({
|
|
219
|
+
elementName: 'my-niivue-viewer',
|
|
220
|
+
sceneElementName: 'my-niivue-scene',
|
|
221
|
+
})
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Exports
|
|
225
|
+
|
|
226
|
+
The package exports `NiivueViewerElement`, `NiivueSceneElement`, `NvSceneController`, `defaultLayouts`, `defaultSliceLayouts`, `defaultViewerOptions`, `DRAG_MODE`, `SLICE_TYPE`, and NiiVue types.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface CanvasPosition {
|
|
2
|
+
top: string;
|
|
3
|
+
left: string;
|
|
4
|
+
width: string;
|
|
5
|
+
height: string;
|
|
6
|
+
}
|
|
7
|
+
export type LayoutFunction = (containerElement: HTMLElement, index: number, total: number) => CanvasPosition;
|
|
8
|
+
export interface LayoutConfig {
|
|
9
|
+
slots: number;
|
|
10
|
+
label: string;
|
|
11
|
+
layoutFunction: LayoutFunction;
|
|
12
|
+
}
|
|
13
|
+
export declare const layout1x1: LayoutFunction;
|
|
14
|
+
export declare const layout2x2: LayoutFunction;
|
|
15
|
+
export declare const layout1x2: LayoutFunction;
|
|
16
|
+
export declare const layout2x1: LayoutFunction;
|
|
17
|
+
export declare const layout1x3: LayoutFunction;
|
|
18
|
+
export declare const layout3x1: LayoutFunction;
|
|
19
|
+
export declare const layout3x3: LayoutFunction;
|
|
20
|
+
export declare const defaultLayouts: Record<string, LayoutConfig>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { NiiVueOptions, NVImage, default as NiiVue, DRAG_MODE, SLICE_TYPE } from '@niivue/niivue';
|
|
2
|
+
import { LitElement, PropertyValues } from 'lit';
|
|
3
|
+
import { defaultLayouts } from './layouts';
|
|
4
|
+
import { defaultSliceLayouts, defaultViewerOptions, NvSceneController, NvSceneControllerSnapshot, SliceLayoutTile } from './nvscene-controller';
|
|
5
|
+
import { ImageFromUrlOptions } from './types';
|
|
6
|
+
export declare const defaultElementName = "niivue-viewer";
|
|
7
|
+
export declare const defaultSceneElementName = "niivue-scene";
|
|
8
|
+
export type NiivueWebComponentOptions = {
|
|
9
|
+
elementName?: string;
|
|
10
|
+
sceneElementName?: string;
|
|
11
|
+
};
|
|
12
|
+
type VolumeVisualProps = {
|
|
13
|
+
colormap?: string;
|
|
14
|
+
calMin?: number;
|
|
15
|
+
calMax?: number;
|
|
16
|
+
opacity?: number;
|
|
17
|
+
};
|
|
18
|
+
export declare const volumeKey: (opts: ImageFromUrlOptions) => string;
|
|
19
|
+
export declare const volumeIdentity: (volume: Pick<NVImage, "url" | "name">) => string;
|
|
20
|
+
export declare const extractVisualProps: (opts: ImageFromUrlOptions) => VolumeVisualProps;
|
|
21
|
+
export declare const volumeVisualUpdates: (next: VolumeVisualProps, prev: VolumeVisualProps) => Partial<VolumeVisualProps>;
|
|
22
|
+
export declare const volumeIndexByKey: (volumes: Pick<NVImage, "url" | "name">[], key: string) => number;
|
|
23
|
+
export declare class NiivueViewerElement extends LitElement {
|
|
24
|
+
static properties: {
|
|
25
|
+
volumes: {
|
|
26
|
+
attribute: boolean;
|
|
27
|
+
};
|
|
28
|
+
options: {
|
|
29
|
+
attribute: boolean;
|
|
30
|
+
};
|
|
31
|
+
sliceType: {
|
|
32
|
+
type: NumberConstructor;
|
|
33
|
+
attribute: string;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
static styles: import('lit').CSSResult;
|
|
37
|
+
volumes: ImageFromUrlOptions[];
|
|
38
|
+
options: Partial<NiiVueOptions>;
|
|
39
|
+
sliceType: 0;
|
|
40
|
+
private niivue;
|
|
41
|
+
private resizeObserver;
|
|
42
|
+
private loadedVolumes;
|
|
43
|
+
private attachmentReady;
|
|
44
|
+
private attachmentGeneration;
|
|
45
|
+
get nv(): NiiVue | null;
|
|
46
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
47
|
+
firstUpdated(): void;
|
|
48
|
+
updated(changed: PropertyValues<this>): void;
|
|
49
|
+
disconnectedCallback(): void;
|
|
50
|
+
private emitError;
|
|
51
|
+
private ownsAttachment;
|
|
52
|
+
private getAttachedNiivue;
|
|
53
|
+
setColormap(volumeIndex: number, colormap: string): Promise<void>;
|
|
54
|
+
setOpacity(volumeIndex: number, opacity: number): Promise<void>;
|
|
55
|
+
setCalMinMax(volumeIndex: number, calMin: number, calMax: number): Promise<void>;
|
|
56
|
+
setColorbarVisible(visible: boolean): void;
|
|
57
|
+
setCrosshairVisible(visible: boolean): void;
|
|
58
|
+
setPrimaryDragMode(mode: number): void;
|
|
59
|
+
setSecondaryDragMode(mode: number): void;
|
|
60
|
+
private syncVolumes;
|
|
61
|
+
private reconcileVolumeOrder;
|
|
62
|
+
}
|
|
63
|
+
export declare class NiivueSceneElement extends LitElement {
|
|
64
|
+
static properties: {
|
|
65
|
+
layout: {
|
|
66
|
+
type: StringConstructor;
|
|
67
|
+
};
|
|
68
|
+
broadcasting: {
|
|
69
|
+
type: BooleanConstructor;
|
|
70
|
+
reflect: boolean;
|
|
71
|
+
};
|
|
72
|
+
snapshot: {
|
|
73
|
+
attribute: boolean;
|
|
74
|
+
};
|
|
75
|
+
};
|
|
76
|
+
static styles: import('lit').CSSResult;
|
|
77
|
+
layout: string;
|
|
78
|
+
broadcasting: boolean;
|
|
79
|
+
snapshot: NvSceneControllerSnapshot;
|
|
80
|
+
readonly scene: NvSceneController;
|
|
81
|
+
private unsubscribe;
|
|
82
|
+
private resizeObserver;
|
|
83
|
+
constructor();
|
|
84
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
85
|
+
firstUpdated(): void;
|
|
86
|
+
updated(changed: PropertyValues<this>): void;
|
|
87
|
+
disconnectedCallback(): void;
|
|
88
|
+
addViewer(options?: Partial<NiiVueOptions>): Promise<import('./nvscene-controller').ViewerSlot>;
|
|
89
|
+
removeViewer(index: number): void;
|
|
90
|
+
canAddViewer(): boolean;
|
|
91
|
+
setViewerSliceLayout(index: number, layout: SliceLayoutTile[] | null): void;
|
|
92
|
+
loadVolume(index: number, opts: ImageFromUrlOptions): Promise<NVImage>;
|
|
93
|
+
loadVolumes(index: number, opts: ImageFromUrlOptions[]): Promise<NVImage[]>;
|
|
94
|
+
removeVolume(index: number, url: string): Promise<void>;
|
|
95
|
+
setColormap(viewerIndex: number, volumeIndex: number, colormap: string): Promise<void>;
|
|
96
|
+
setOpacity(viewerIndex: number, volumeIndex: number, opacity: number): Promise<void>;
|
|
97
|
+
setCalMinMax(viewerIndex: number, volumeIndex: number, calMin: number, calMax: number): Promise<void>;
|
|
98
|
+
setColorbarVisible(visible: boolean, viewerIndex?: number): void;
|
|
99
|
+
setCrosshairVisible(visible: boolean, viewerIndex?: number): void;
|
|
100
|
+
setPrimaryDragMode(mode: number, viewerIndex?: number): void;
|
|
101
|
+
setSecondaryDragMode(mode: number, viewerIndex?: number): void;
|
|
102
|
+
private forEachTargetViewer;
|
|
103
|
+
private forwardSceneEvents;
|
|
104
|
+
}
|
|
105
|
+
export declare function defineNiivueWebComponents(options?: NiivueWebComponentOptions): void;
|
|
106
|
+
export type { ImageFromUrlOptions, NiiVueOptions, NVImage };
|
|
107
|
+
export { DRAG_MODE, defaultLayouts, defaultSliceLayouts, defaultViewerOptions, NvSceneController, SLICE_TYPE, };
|