@niivue/nv-ohif 1.0.0-rc.2 → 1.0.0-rc.4

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/dist/index.js CHANGED
@@ -1421,7 +1421,6 @@ function ohifToolToAnnotationTool(tool) {
1421
1421
  return null;
1422
1422
  }
1423
1423
  }
1424
- var UNSUPPORTED_MEASUREMENT_TOOLS = new Set;
1425
1424
  function ohifToolToDragMode(tool) {
1426
1425
  switch (tool) {
1427
1426
  case "WindowLevel":
@@ -1433,10 +1432,6 @@ function ohifToolToDragMode(tool) {
1433
1432
  case "Angle":
1434
1433
  case "CobbAngle":
1435
1434
  return DRAG_MODE.angle;
1436
- case "RectangleROI":
1437
- case "EllipticalROI":
1438
- case "CircleROI":
1439
- return DRAG_MODE.roiSelection;
1440
1435
  default:
1441
1436
  return DRAG_MODE.crosshair;
1442
1437
  }
@@ -1973,6 +1968,16 @@ function NiivueViewport(props) {
1973
1968
  if (!container)
1974
1969
  return;
1975
1970
  let disposed = false;
1971
+ let noteTimeout;
1972
+ const flashNote = (message, ms = 2000) => {
1973
+ window.clearTimeout(noteTimeout);
1974
+ const note = { kind: "note", message };
1975
+ setStatus(note);
1976
+ noteTimeout = window.setTimeout(() => {
1977
+ noteTimeout = undefined;
1978
+ setStatus((current) => current === note ? { kind: "idle" } : current);
1979
+ }, ms);
1980
+ };
1976
1981
  let annotationOverlay = null;
1977
1982
  let unregisterAnnotation = null;
1978
1983
  const canvas = document.createElement("canvas");
@@ -2008,8 +2013,7 @@ function NiivueViewport(props) {
2008
2013
  if (!wl)
2009
2014
  return;
2010
2015
  const message = `W: ${Math.round(wl.window)} L: ${Math.round(wl.level)}`;
2011
- setStatus({ kind: "note", message });
2012
- window.setTimeout(() => setStatus((s) => s.kind === "note" && s.message === message ? { kind: "idle" } : s), 2000);
2016
+ flashNote(message);
2013
2017
  };
2014
2018
  canvas.addEventListener("pointerup", onPointerUp);
2015
2019
  const onAnnotationAdded = (e) => {
@@ -2024,8 +2028,7 @@ function NiivueViewport(props) {
2024
2028
  if (!added || !stats)
2025
2029
  return;
2026
2030
  const message = stats.length !== undefined ? `Length: ${stats.length.toFixed(1)} mm` : `Area: ${stats.area.toFixed(1)} mm²`;
2027
- setStatus({ kind: "note", message });
2028
- window.setTimeout(() => setStatus((s) => s.kind === "note" && s.message === message ? { kind: "idle" } : s), 2000);
2031
+ flashNote(message);
2029
2032
  };
2030
2033
  const onAnnotationRemoved = (e) => {
2031
2034
  const id = e.detail?.id;
@@ -2044,6 +2047,7 @@ function NiivueViewport(props) {
2044
2047
  const unsubscribeLabelSync = subscribeOhifLabelSync(servicesManagerRef.current);
2045
2048
  return () => {
2046
2049
  disposed = true;
2050
+ window.clearTimeout(noteTimeout);
2047
2051
  setReady(false);
2048
2052
  clearNiivueAnnotations(viewportId, servicesManagerRef.current);
2049
2053
  unregisterNiivue(viewportId);
@@ -2247,11 +2251,6 @@ function NiivueViewport(props) {
2247
2251
  } else {
2248
2252
  nv.annotationIsEnabled = false;
2249
2253
  nv.primaryDragMode = ohifToolToDragMode(tool);
2250
- if (tool && UNSUPPORTED_MEASUREMENT_TOOLS.has(tool)) {
2251
- const message = `${tool} is not supported in NiiVue`;
2252
- setStatus({ kind: "note", message });
2253
- window.setTimeout(() => setStatus((s) => s.kind === "note" && s.message === message ? { kind: "idle" } : s), 2500);
2254
- }
2255
2254
  }
2256
2255
  slideViewRef.current?.setTool(tool);
2257
2256
  };
@@ -2481,6 +2480,31 @@ function getNiivueSopClassHandlerModule() {
2481
2480
  const seriesUID = String(first2.SeriesInstanceUID ?? "");
2482
2481
  const imageIds = instances2.map((inst) => inst.imageId).filter((id) => typeof id === "string");
2483
2482
  const description = String(first2.SeriesDescription ?? "Whole-slide image");
2483
+ let thumbnailPromise;
2484
+ const getThumbnailSrc = (options) => {
2485
+ const signal = options?.signal;
2486
+ if (signal?.aborted)
2487
+ return Promise.resolve(null);
2488
+ thumbnailPromise ??= fetchWsiThumbnailObjectUrl(instances2, authHeaders(undefined)).then((src) => {
2489
+ if (src === null)
2490
+ thumbnailPromise = undefined;
2491
+ return src;
2492
+ }, () => {
2493
+ thumbnailPromise = undefined;
2494
+ return null;
2495
+ });
2496
+ if (!signal)
2497
+ return thumbnailPromise;
2498
+ const pending = thumbnailPromise;
2499
+ return new Promise((resolve) => {
2500
+ const onAbort = () => resolve(null);
2501
+ signal.addEventListener("abort", onAbort, { once: true });
2502
+ pending.then((src) => {
2503
+ signal.removeEventListener("abort", onAbort);
2504
+ resolve(signal.aborted ? null : src);
2505
+ });
2506
+ });
2507
+ };
2484
2508
  const displaySet = {
2485
2509
  displaySetInstanceUID: `${seriesUID}-niivue-wsi`,
2486
2510
  SOPClassHandlerId: NIIVUE_SOP_CLASS_HANDLER_ID,
@@ -2494,7 +2518,7 @@ function getNiivueSopClassHandlerModule() {
2494
2518
  numInstances: instances2.length,
2495
2519
  instances: instances2,
2496
2520
  imageIds,
2497
- getThumbnailSrc: (options) => fetchWsiThumbnailObjectUrl(instances2, authHeaders(undefined), options?.signal),
2521
+ getThumbnailSrc,
2498
2522
  label: description
2499
2523
  };
2500
2524
  return [displaySet];
@@ -7,10 +7,5 @@ import { type AnnotationTool } from '@niivue/niivue';
7
7
  * compute ROI stats (area/mean) and fire `annotationAdded` with them.
8
8
  */
9
9
  export declare function ohifToolToAnnotationTool(tool: string | undefined): AnnotationTool | null;
10
- /**
11
- * OHIF measurement tools NiiVue cannot back yet (no core primitive). Activating
12
- * one shows a brief 'not supported' status and keeps safe crosshair navigation.
13
- */
14
- export declare const UNSUPPORTED_MEASUREMENT_TOOLS: ReadonlySet<string>;
15
10
  /** Map an OHIF primary tool name to NiiVue's matching left-drag mode. */
16
11
  export declare function ohifToolToDragMode(tool: string | undefined): number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@niivue/nv-ohif",
3
- "version": "1.0.0-rc.2",
3
+ "version": "1.0.0-rc.4",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "NiiVue viewport extension for the OHIF Viewer (render series with NiiVue: 3D volume rendering, meshes, overlays, multiplanar, drawing).",
@@ -28,18 +28,18 @@
28
28
  },
29
29
  "comment:peers": "The host OHIF app (>= 3.12, React 18) provides @ohif/core, @ohif/extension-default and react-dom. They are intentionally NOT peerDependencies here: bun would install the whole OHIF tree (pinned to react-dom 18) into this monorepo, colliding with @niivue/nvreact (React 19). This package builds against local OHIF typings (src/ohif-types.ts) and externalizes react. The react peer allows 18 or 19 so bun reuses the monorepo's React 19 for dev; the component's simple hook usage is compatible with both, and the OHIF host supplies React 18 at runtime.",
30
30
  "peerDependencies": {
31
- "@niivue/niivue": "1.0.0-rc.15",
31
+ "@niivue/niivue": "1.0.0-rc.17",
32
32
  "react": "^18.3.1 || ^19"
33
33
  },
34
34
  "comment:dcm2niix-pin": "The dcm2niix Web-Worker exit fix (wrap callMain in try/catch, read err.status) is PUBLISHED: @niivue/dcm2niix 1.3.20260724 (calendar-versioned, now npm 'latest') contains it (verified in the published dist/worker.js + worker.jpeg.js). The pin requires that fixed release or newer, so DICOM conversion now works for npm-install consumers. The dev-rig local-patched dcm2niix override can be dropped in favor of the published package. See README '## DICOM support'.",
35
35
  "comment:uikit-dep": "@niivue/uikit is externalized in build:lib and is a runtime dependency (its ruler/line/text overlays, loadDefaultFont, and the inlined MSDF font are imported at runtime, not bundled). It is published from this monorepo in the same Nx release group, so `npm install @niivue/nv-ohif` resolves it. The workspace range is rewritten to the published version on pack/release. Its only @niivue/niivue import is type-only, so no niivue runtime is duplicated.",
36
36
  "dependencies": {
37
37
  "@niivue/dcm2niix": "^1.3.20260724",
38
- "@niivue/uikit": "1.0.0-rc.2",
38
+ "@niivue/uikit": "1.0.0-rc.4",
39
39
  "dcmjs": "^0.49.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@niivue/niivue": "1.0.0-rc.15",
42
+ "@niivue/niivue": "1.0.0-rc.17",
43
43
  "@types/bun": "^1.3.12",
44
44
  "@types/react": "^19",
45
45
  "@types/react-dom": "^19",