@ohif/app 3.13.0-beta.5 → 3.13.0-beta.51

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.
Files changed (70) hide show
  1. package/dist/{1459.bundle.61caf834dbb820188bc4.js → 1459.bundle.03f6812bbebed223ac0a.js} +5 -6
  2. package/dist/{147.bundle.37d627289453cb6c3937.js → 147.bundle.3c8fa1f478644636898a.js} +21 -45
  3. package/dist/{1608.bundle.0687c661f1c9edfb3b8a.js → 1608.bundle.c10d9aef452fe5a86d77.js} +12 -12
  4. package/dist/{1927.bundle.3050588e95f43cf57cdd.js → 1927.bundle.be67b3aafe238ca9f191.js} +27 -38
  5. package/dist/{1933.bundle.afeaf853f1b9bb471d09.js → 1933.bundle.d1c853d4459eabcac0fc.js} +32 -27
  6. package/dist/{2018.bundle.f94c5a365f20da582cce.js → 2018.bundle.df77dcb95a7eb7194752.js} +18 -19
  7. package/dist/{6409.bundle.b36048896cb11c8571fb.js → 2075.bundle.0e69a126a39539ff8e9a.js} +308 -237
  8. package/dist/{2108.bundle.e84aa8d858d8c4f2413e.js → 2108.bundle.aea8d3b39486dd5ab39e.js} +569 -558
  9. package/dist/{213.bundle.b03e90c6260533129e4a.js → 213.bundle.4f2dc5a26c4bdfea9038.js} +3 -5
  10. package/dist/{2424.bundle.36b384fa160f62791af2.js → 2424.bundle.225f1b88d037ff1e8d2b.js} +3 -5
  11. package/dist/{2516.bundle.1ea0988d309a757bb6da.js → 2516.bundle.f62228e9a800de8d4b31.js} +6 -6
  12. package/dist/{2701.bundle.12bd01a80a9f8ea4cd94.js → 2701.bundle.28b3ca0e6ae5a13f78b3.js} +10 -10
  13. package/dist/{1730.bundle.9ccc50f800b3dce59bed.js → 3138.bundle.5594231be4399fa822f2.js} +14 -308
  14. package/dist/{3461.bundle.f63b5cb53237ed77e684.js → 3461.bundle.c453ad511e18741f5b36.js} +126 -107
  15. package/dist/{4202.bundle.5a0f8e4004c5d8a68548.js → 4202.bundle.f11f02596e30a22d1105.js} +6 -6
  16. package/dist/{4019.bundle.83a604779f7da0101ced.js → 4287.bundle.b7840e7b94cbbc102236.js} +348 -237
  17. package/dist/{5462.bundle.21beddaca145b7465c72.js → 4406.bundle.573d234b4641d23cf8db.js} +1083 -1308
  18. package/dist/{1403.bundle.8b63385cd43188c65459.js → 4507.bundle.152cf927b86b6e295b7f.js} +10 -305
  19. package/dist/{3081.bundle.81ed137529d1fb98d456.js → 4688.bundle.05c4c23606587b3e82bd.js} +657 -382
  20. package/dist/{4819.bundle.2085e6422ae2249830c4.js → 4819.bundle.b29eaf88762b95912d1d.js} +37 -37
  21. package/dist/{4775.bundle.308d5e29044a36b3039f.js → 5015.bundle.322992b6dcb647ecf70e.js} +29 -333
  22. package/dist/{5028.bundle.af59f031d8564db81587.js → 5028.bundle.d5e5ec2e2fae9a8c0dfa.js} +11 -13
  23. package/dist/{5261.bundle.6e1a017f8f1027557f5b.js → 5261.bundle.2655560097e9250eac44.js} +412 -345
  24. package/dist/{5457.bundle.59d61b8ad0daad3b8094.js → 5457.bundle.bd64924038b08fa7154b.js} +16 -23
  25. package/dist/{5485.bundle.238541403cdc7dd4ad60.js → 5485.bundle.538097cf423423cc9cae.js} +20 -32
  26. package/dist/{5491.bundle.2e01dd7ad29e4cc01bc1.js → 5491.bundle.4866d2ecb20dd089e071.js} +54 -51
  27. package/dist/{5802.bundle.3bf5e6b3ab330a594a47.js → 5802.bundle.8b2c04396d68ba668af5.js} +77 -18
  28. package/dist/5802.css +1 -1
  29. package/dist/{5830.bundle.b073c265c4fcea1afff3.js → 5830.bundle.791019deddd536980a11.js} +3 -3
  30. package/dist/{5858.bundle.ff6b340cf7457db76a1a.js → 5858.bundle.466e58128de344ab53f3.js} +90 -86
  31. package/dist/{6027.bundle.6cab80c16ed182c98ef7.js → 6027.bundle.f36aa36a2281dff6e29b.js} +3 -5
  32. package/dist/{6354.bundle.c387737dc09c9cab4ff2.js → 6354.bundle.929febcf6d326e582e00.js} +151 -140
  33. package/dist/{6376.bundle.9cb74d7bc08476e2f1a7.js → 6376.bundle.839c708f2fc41e76ee58.js} +6 -6
  34. package/dist/{2842.bundle.860b9f10fcdd9656947a.js → 6386.bundle.e75a2f70039dfe42f935.js} +886 -2297
  35. package/dist/6939.bundle.41fbdef87597b5172ec6.js +3 -3
  36. package/dist/{7159.bundle.a5991a5d4f0dd8f1c95f.js → 7159.bundle.fb9df255868960f69765.js} +7 -5
  37. package/dist/{7190.bundle.e8f0193e0e06472f795c.js → 7190.bundle.6314b558746e394aeb0e.js} +40 -40
  38. package/dist/{732.bundle.6978ac30a1e36abf06db.js → 732.bundle.ea6f9d8504e37e01a208.js} +5 -13
  39. package/dist/{7431.bundle.b01791d10e6cf9f503b0.js → 7431.bundle.5e14641f2c71e852abe7.js} +28 -28
  40. package/dist/{4410.bundle.c5224cd7d6238a7d4660.js → 7537.bundle.1c612642a1e8a96179ed.js} +5180 -2219
  41. package/dist/{7639.bundle.b32630bff861ac1b8e89.js → 7639.bundle.f89778f572ee3caeb6fb.js} +3 -5
  42. package/dist/7758.bundle.c8d106364298e7d288f0.js +3 -3
  43. package/dist/{8094.bundle.5c44190a325ac23e3e5c.js → 8094.bundle.148a66619607e37cbf19.js} +3 -4
  44. package/dist/{8305.bundle.0cbccd2240389ee9a4a4.js → 8305.bundle.accd9d9b56fd08402c9e.js} +69 -64
  45. package/dist/{6163.bundle.53852173360d1a4a1480.js → 8499.bundle.26a487dbfa7be0837750.js} +7 -302
  46. package/dist/8499.css +2 -0
  47. package/dist/{85.bundle.62bab793d6689f8a1ec2.js → 85.bundle.85120dcfbb03af4fa5a7.js} +3 -5
  48. package/dist/{8558.bundle.80aa787d04cd852a2c00.js → 8558.bundle.c778f722abdb0a66bc34.js} +15 -309
  49. package/dist/{8583.bundle.ab0e069832ce2a6c9844.js → 8583.bundle.243229c3ff277630ddb8.js} +22 -25
  50. package/dist/{6347.bundle.784c48912700f281de1d.js → 8963.bundle.0f106869f9d0eb0bba03.js} +534 -570
  51. package/dist/{997.bundle.822b33e561263084e18c.js → 9039.bundle.6c84d903d5baaecf2f3a.js} +3817 -2912
  52. package/dist/{9195.bundle.8016f417b67b2eb1c1f4.js → 9195.bundle.95ca6983f6a87e433d79.js} +239 -152
  53. package/dist/{7412.bundle.fab1742191b7fe937330.js → 9205.bundle.9a5f5dd04fd0831d9a4a.js} +5942 -3253
  54. package/dist/{3584.bundle.8cc0750425513433e9cc.js → 9567.bundle.be350438bed4e656f278.js} +3422 -2880
  55. package/dist/{9845.bundle.255e7c7f7a88193b4e47.js → 9845.bundle.36b3563ae1dba65b6b9a.js} +10 -10
  56. package/dist/{9862.bundle.3a8958a82c572015d25d.js → 9862.bundle.51a1e7030f6b635d9528.js} +8 -6
  57. package/dist/{9927.bundle.8dc1813e602296f01090.js → 9927.bundle.fa13d8f3b034e48c00d3.js} +4 -6
  58. package/dist/app.bundle.css +3 -3
  59. package/dist/{app.bundle.a4ba14820ccf58a3956c.js → app.bundle.f5b1d8747965f98a72a8.js} +94613 -92508
  60. package/dist/{polySeg.bundle.a5aa9130b4191253c410.js → compute.bundle.ba3878791df68055b11d.js} +8 -20
  61. package/dist/{histogram-worker.bundle.d4e40a8018d2698b072e.js → histogram-worker.bundle.a2a50c4674d99c619ca7.js} +11 -23
  62. package/dist/index.html +1 -1
  63. package/dist/{interpolation.bundle.c70cb95d164dc494e6dc.js → interpolation.bundle.53073c15cca1c5a41ae4.js} +14 -26
  64. package/dist/{compute.bundle.64280c7af19ff567465f.js → polySeg.bundle.70369a8c69b843375431.js} +10 -22
  65. package/dist/sw.js +1 -1
  66. package/package.json +23 -22
  67. package/dist/3343.bundle.d7578ce8f75d158c0bab.js +0 -297
  68. /package/dist/{1730.css → 3138.css} +0 -0
  69. /package/dist/{3343.css → 4972.css} +0 -0
  70. /package/dist/{6163.css → 7829.css} +0 -0
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[3081],{
2
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[4688],{
3
3
 
4
- /***/ 38007:
5
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
4
+ /***/ 38007
5
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
6
6
 
7
7
 
8
8
  // EXPORTS
@@ -25,8 +25,8 @@ var useSegmentations = __webpack_require__(73421);
25
25
  var useViewportSegmentations = __webpack_require__(79063);
26
26
  // EXTERNAL MODULE: ../../../node_modules/react/index.js
27
27
  var react = __webpack_require__(86326);
28
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3075 modules
29
- var src = __webpack_require__(12517);
28
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3076 modules
29
+ var src = __webpack_require__(2343);
30
30
  ;// ../../../extensions/cornerstone/src/hooks/useViewportHover.ts
31
31
 
32
32
 
@@ -109,15 +109,15 @@ var useViewportRendering = __webpack_require__(47488);
109
109
 
110
110
 
111
111
 
112
- /***/ }),
112
+ /***/ },
113
113
 
114
- /***/ 9234:
115
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
114
+ /***/ 9234
115
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
116
116
 
117
117
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
118
118
  /* harmony export */ c: () => (/* binding */ useActiveViewportSegmentationRepresentations)
119
119
  /* harmony export */ });
120
- /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12517);
120
+ /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2343);
121
121
  /* harmony import */ var _useViewportSegmentations__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(79063);
122
122
 
123
123
 
@@ -131,10 +131,10 @@ function useActiveViewportSegmentationRepresentations() {
131
131
  }
132
132
 
133
133
 
134
- /***/ }),
134
+ /***/ },
135
135
 
136
- /***/ 84535:
137
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
136
+ /***/ 84535
137
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
138
138
 
139
139
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
140
140
  /* harmony export */ R: () => (/* binding */ useMeasurementTracking)
@@ -238,10 +238,10 @@ function useMeasurementTracking({
238
238
  }
239
239
  /* unused harmony default export */ var __WEBPACK_DEFAULT_EXPORT__ = ((/* unused pure expression or super */ null && (useMeasurementTracking)));
240
240
 
241
- /***/ }),
241
+ /***/ },
242
242
 
243
- /***/ 19214:
244
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
243
+ /***/ 19214
244
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
245
245
 
246
246
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
247
247
  /* harmony export */ d: () => (/* binding */ useMeasurements)
@@ -348,10 +348,10 @@ function useMeasurements({
348
348
  return displayMeasurements;
349
349
  }
350
350
 
351
- /***/ }),
351
+ /***/ },
352
352
 
353
- /***/ 73421:
354
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
353
+ /***/ 73421
354
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
355
355
 
356
356
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
357
357
  /* harmony export */ j: () => (/* binding */ useSegmentations)
@@ -483,10 +483,10 @@ function useSegmentations(options) {
483
483
  return segmentations;
484
484
  }
485
485
 
486
- /***/ }),
486
+ /***/ },
487
487
 
488
- /***/ 10225:
489
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
488
+ /***/ 10225
489
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
490
490
 
491
491
 
492
492
  // EXPORTS
@@ -498,8 +498,8 @@ __webpack_require__.d(__webpack_exports__, {
498
498
  var react = __webpack_require__(86326);
499
499
  // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
500
500
  var src = __webpack_require__(42356);
501
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3075 modules
502
- var ui_next_src = __webpack_require__(12517);
501
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3076 modules
502
+ var ui_next_src = __webpack_require__(2343);
503
503
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 1 modules
504
504
  var esm = __webpack_require__(15327);
505
505
  ;// ../../../extensions/cornerstone/src/components/ViewportDataOverlaySettingMenu/utils.ts
@@ -575,7 +575,7 @@ function getEnhancedDisplaySets({
575
575
  }
576
576
 
577
577
  // Check if Frame of Reference matches
578
- if (displaySet.FrameOfReferenceUID && displaySet.FrameOfReferenceUID !== backgroundDisplaySet.FrameOfReferenceUID) {
578
+ if (displaySet.frameOfReferenceUID && displaySet.frameOfReferenceUID !== backgroundDisplaySet.frameOfReferenceUID) {
579
579
  return {
580
580
  ...displaySet,
581
581
  isOverlayable: false
@@ -805,10 +805,10 @@ function useViewportDisplaySets(viewportId, options) {
805
805
  return result;
806
806
  }
807
807
 
808
- /***/ }),
808
+ /***/ },
809
809
 
810
- /***/ 47488:
811
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
810
+ /***/ 47488
811
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
812
812
 
813
813
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
814
814
  /* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__),
@@ -818,7 +818,9 @@ function useViewportDisplaySets(viewportId, options) {
818
818
  /* harmony import */ var _ohif_core__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(42356);
819
819
  /* harmony import */ var _useViewportDisplaySets__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(10225);
820
820
  /* harmony import */ var _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(15327);
821
- /* harmony import */ var _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(93813);
821
+ /* harmony import */ var _utils_getDataIdForViewport__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(67142);
822
+ /* harmony import */ var _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(93813);
823
+
822
824
 
823
825
 
824
826
 
@@ -826,13 +828,13 @@ function useViewportDisplaySets(viewportId, options) {
826
828
 
827
829
  const getPosition = location => {
828
830
  switch (location) {
829
- case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_4__/* .ButtonLocation */ .ij.LeftMiddle:
831
+ case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__/* .ButtonLocation */ .ij.LeftMiddle:
830
832
  return 'left';
831
- case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_4__/* .ButtonLocation */ .ij.RightMiddle:
833
+ case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__/* .ButtonLocation */ .ij.RightMiddle:
832
834
  return 'right';
833
- case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_4__/* .ButtonLocation */ .ij.BottomMiddle:
835
+ case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__/* .ButtonLocation */ .ij.BottomMiddle:
834
836
  return 'bottom';
835
- case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_4__/* .ButtonLocation */ .ij.TopMiddle:
837
+ case _ohif_core_src_services_ToolBarService_ToolbarService__WEBPACK_IMPORTED_MODULE_5__/* .ButtonLocation */ .ij.TopMiddle:
836
838
  return 'top';
837
839
  default:
838
840
  return 'bottom';
@@ -846,13 +848,6 @@ const linearToOpacity = linearValue => {
846
848
  const opacityToLinear = opacityValue => {
847
849
  return Math.pow(opacityValue, 1.0 / GAMMA);
848
850
  };
849
- const is3DViewport = ({
850
- viewportId,
851
- cornerstoneViewportService
852
- }) => {
853
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
854
- return viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.VolumeViewport3D;
855
- };
856
851
 
857
852
  /**
858
853
  * Hook to access window level functionality for a specific viewport
@@ -871,14 +866,13 @@ function useViewportRendering(viewportId, options) {
871
866
  colorbarService,
872
867
  customizationService
873
868
  } = servicesManager.services;
874
- const [is3DVolume, setIs3DVolume] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(is3DViewport({
875
- viewportId,
876
- cornerstoneViewportService
877
- }));
878
869
  const [hasColorbar, setHasColorbar] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(colorbarService.hasColorbar(viewportId));
879
870
  const [colorbarPosition, setColorbarPosition] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(options?.location ? getPosition(options.location) : 'bottom');
880
871
  const [voiRange, setVoiRange] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)();
881
872
  const voiRangeRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef();
873
+ // Viewport from service; kept in state so we can subscribe to VIEWPORT_DATA_CHANGED when null and re-run effects when it becomes available
874
+ const [viewport, setViewport] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(() => viewportId ? cornerstoneViewportService.getCornerstoneViewport(viewportId) ?? null : null);
875
+ const [is3DVolume, setIs3DVolume] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.VolumeViewport3D);
882
876
  const [opacity, setOpacityState] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)();
883
877
  const [opacityLinear, setOpacityLinearState] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)();
884
878
  const [threshold, setThresholdState] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)();
@@ -922,6 +916,35 @@ function useViewportRendering(viewportId, options) {
922
916
  }) || [];
923
917
  }, [viewportDisplaySets, presets]);
924
918
 
919
+ // Keep viewport in state; when not available, subscribe to VIEWPORT_DATA_CHANGED so we set it when the viewport is ready
920
+ (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
921
+ if (!viewportId) {
922
+ setViewport(null);
923
+ return;
924
+ }
925
+ const vp = cornerstoneViewportService.getCornerstoneViewport(viewportId);
926
+ setViewport(vp ?? null);
927
+ if (vp) {
928
+ return;
929
+ }
930
+ const {
931
+ unsubscribe
932
+ } = cornerstoneViewportService.subscribe(cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED, ({
933
+ viewportId: eventViewportId
934
+ }) => {
935
+ if (eventViewportId !== viewportId) {
936
+ return;
937
+ }
938
+ const next = cornerstoneViewportService.getCornerstoneViewport(viewportId);
939
+ if (next) {
940
+ setViewport(next);
941
+ }
942
+ });
943
+ return () => {
944
+ unsubscribe();
945
+ };
946
+ }, [viewportId, cornerstoneViewportService]);
947
+
925
948
  // Calculate pixel value range for the active display set
926
949
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
927
950
  if (!activeDisplaySetInstanceUID) {
@@ -931,21 +954,20 @@ function useViewportRendering(viewportId, options) {
931
954
  if (!selectedDisplaySet?.imageIds?.length) {
932
955
  return;
933
956
  }
934
- const csViewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
935
- if (!csViewport) {
957
+ if (!viewport) {
936
958
  return;
937
959
  }
938
- if (!(csViewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport)) {
960
+ if (!(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport)) {
939
961
  return;
940
962
  }
941
- const volumeIds = csViewport.getAllVolumeIds();
963
+ const volumeIds = viewport.getAllVolumeIds();
942
964
  const volumeId = volumeIds.find(id => id.includes(activeDisplaySetInstanceUID));
943
965
  if (!volumeId) {
944
966
  return;
945
967
  }
946
968
 
947
969
  // only handle volume viewports for now
948
- const imageData = csViewport.getImageData(volumeId);
970
+ const imageData = viewport.getImageData(volumeId);
949
971
  if (!imageData) {
950
972
  return;
951
973
  }
@@ -958,7 +980,7 @@ function useViewportRendering(viewportId, options) {
958
980
  min: range[0],
959
981
  max: range[1]
960
982
  });
961
- }, [activeDisplaySetInstanceUID, displaySetService, cornerstoneViewportService, viewportId]);
983
+ }, [activeDisplaySetInstanceUID, displaySetService, viewport]);
962
984
 
963
985
  // Get the presets specifically for the active display set
964
986
  const activeDisplaySetPresets = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {
@@ -972,52 +994,33 @@ function useViewportRendering(viewportId, options) {
972
994
  return activePresetData.presets;
973
995
  }, [allWindowLevelPresets, activeDisplaySetInstanceUID]);
974
996
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
975
- setIs3DVolume(is3DViewport({
976
- viewportId,
977
- cornerstoneViewportService
978
- }));
979
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
980
-
981
- // Initialize the VOI range from the viewport
982
- if (viewport && activeDisplaySetInstanceUID) {
983
- try {
984
- let properties;
985
- if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.StackViewport) {
986
- properties = viewport.getProperties();
987
- if (properties.voiRange) {
988
- setVoiRange(properties.voiRange);
989
- voiRangeRef.current = properties.voiRange;
990
- }
991
- } else if (viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport) {
992
- // For volume viewports, find the actor for the active display set
993
- const volumeIds = viewport.getAllVolumeIds();
994
- const volumeId = volumeIds.find(id => id.includes(activeDisplaySetInstanceUID));
995
- if (volumeId) {
996
- properties = viewport.getProperties(volumeId);
997
- if (properties?.voiRange) {
998
- setVoiRange(properties.voiRange);
999
- voiRangeRef.current = properties.voiRange;
1000
- }
1001
-
1002
- // Get opacity from colormap if available
1003
- if (properties?.colormap?.opacity !== undefined) {
1004
- const isArray = Array.isArray(properties.colormap.opacity);
1005
- const opacity = isArray ? properties.colormap.opacity.reduce((max, current) => Math.max(max, current), 0) : properties.colormap.opacity;
1006
- setOpacityState(opacity);
1007
- setOpacityLinearState(opacityToLinear(opacity));
1008
- }
1009
-
1010
- // Get threshold from colormap if available
1011
- if (properties?.colormap && properties.colormap.threshold !== undefined) {
1012
- setThresholdState(properties.colormap.threshold);
1013
- }
1014
- }
1015
- }
1016
- } catch (error) {
1017
- console.error('Error initializing VOI range:', error);
997
+ setIs3DVolume(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.VolumeViewport3D);
998
+ if (!viewport || !activeDisplaySetInstanceUID) {
999
+ return;
1000
+ }
1001
+ try {
1002
+ const dataId = (0,_utils_getDataIdForViewport__WEBPACK_IMPORTED_MODULE_4__/* .getDataIdForViewport */ .V)(viewport, activeDisplaySetInstanceUID);
1003
+ const properties = dataId != null ? viewport.getProperties(dataId) : viewport.getProperties();
1004
+ if (!properties) {
1005
+ return;
1006
+ }
1007
+ if (properties.voiRange) {
1008
+ setVoiRange(properties.voiRange);
1009
+ voiRangeRef.current = properties.voiRange;
1018
1010
  }
1011
+ if (properties.colormap?.opacity !== undefined) {
1012
+ const opacityVal = properties.colormap.opacity;
1013
+ const opacity = Array.isArray(opacityVal) ? opacityVal.reduce((max, current) => Math.max(max, current), 0) : opacityVal;
1014
+ setOpacityState(opacity);
1015
+ setOpacityLinearState(opacityToLinear(opacity));
1016
+ }
1017
+ if (properties.colormap?.threshold !== undefined) {
1018
+ setThresholdState(properties.colormap.threshold);
1019
+ }
1020
+ } catch (error) {
1021
+ console.error('Error initializing VOI range:', error);
1019
1022
  }
1020
- }, [cornerstoneViewportService, viewportId, activeDisplaySetInstanceUID]);
1023
+ }, [activeDisplaySetInstanceUID, viewport]);
1021
1024
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
1022
1025
  if (!viewportId) {
1023
1026
  return;
@@ -1035,17 +1038,10 @@ function useViewportRendering(viewportId, options) {
1035
1038
  };
1036
1039
  }, [colorbarService, viewportId]);
1037
1040
  (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
1038
- if (!viewportId || !activeDisplaySetInstanceUID) {
1039
- return;
1040
- }
1041
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
1042
- if (!viewport) {
1041
+ if (!activeDisplaySetInstanceUID || !viewport?.element) {
1043
1042
  return;
1044
1043
  }
1045
1044
  const element = viewport.element;
1046
- if (!element) {
1047
- return;
1048
- }
1049
1045
  const updateVOI = eventDetail => {
1050
1046
  const {
1051
1047
  range
@@ -1085,7 +1081,7 @@ function useViewportRendering(viewportId, options) {
1085
1081
  element.removeEventListener(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.Enums.Events.VOI_MODIFIED, updateVOI);
1086
1082
  element.removeEventListener(_cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.Enums.Events.COLORMAP_MODIFIED, updateColormap);
1087
1083
  };
1088
- }, [viewportId, activeDisplaySetInstanceUID, cornerstoneViewportService, opacityToLinear]);
1084
+ }, [activeDisplaySetInstanceUID, viewport, opacityToLinear]);
1089
1085
  const validateActiveDisplaySet = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {
1090
1086
  if (!activeDisplaySetInstanceUID) {
1091
1087
  throw new Error('No active display set instance UID is available');
@@ -1238,12 +1234,8 @@ function useViewportRendering(viewportId, options) {
1238
1234
  },
1239
1235
  context: 'CORNERSTONE'
1240
1236
  });
1241
- }, [commandsManager, viewportId, validateActiveDisplaySet]);
1237
+ }, [commandsManager, validateActiveDisplaySet, viewport, viewportId]);
1242
1238
  const setOpacity = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(opacityValue => {
1243
- if (!viewportId) {
1244
- return;
1245
- }
1246
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
1247
1239
  if (!viewport || !(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport)) {
1248
1240
  return;
1249
1241
  }
@@ -1274,17 +1266,13 @@ function useViewportRendering(viewportId, options) {
1274
1266
  colormap: updatedColormap
1275
1267
  }, volumeId);
1276
1268
  viewport.render();
1277
- }, [cornerstoneViewportService, viewportId, validateActiveDisplaySet, opacityToLinear]);
1269
+ }, [validateActiveDisplaySet, opacityToLinear, viewport]);
1278
1270
  const setOpacityLinear = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(linearValue => {
1279
1271
  // Convert linear UI value to actual opacity value and apply it
1280
1272
  const actualOpacity = linearToOpacity(linearValue);
1281
1273
  setOpacity(actualOpacity);
1282
1274
  }, [linearToOpacity, setOpacity]);
1283
1275
  const setThreshold = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(thresholdValue => {
1284
- if (!viewportId) {
1285
- return;
1286
- }
1287
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
1288
1276
  if (!viewport || !(viewport instanceof _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.BaseVolumeViewport)) {
1289
1277
  return;
1290
1278
  }
@@ -1302,15 +1290,14 @@ function useViewportRendering(viewportId, options) {
1302
1290
  }
1303
1291
  }, volumeId);
1304
1292
  viewport.render();
1305
- }, [cornerstoneViewportService, viewportId, validateActiveDisplaySet]);
1293
+ }, [validateActiveDisplaySet, viewport]);
1306
1294
 
1307
1295
  // Get the current colormap for the active display set
1308
1296
  const colormap = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {
1309
- if (!viewportId || !activeDisplaySetInstanceUID || !viewportDisplaySets?.length) {
1297
+ if (!activeDisplaySetInstanceUID || !viewportDisplaySets?.length) {
1310
1298
  return null;
1311
1299
  }
1312
1300
  try {
1313
- const viewport = cornerstoneViewportService.getCornerstoneViewport(viewportId);
1314
1301
  if (!viewport) {
1315
1302
  return null;
1316
1303
  }
@@ -1339,7 +1326,7 @@ function useViewportRendering(viewportId, options) {
1339
1326
  console.error('Error getting viewport colormap:', error);
1340
1327
  return colorbarProperties?.colormaps?.find(c => c.Name === 'Grayscale') || colorbarProperties?.colormaps?.[0];
1341
1328
  }
1342
- }, [cornerstoneViewportService, viewportId, activeDisplaySetInstanceUID, viewportDisplaySets, colorbarProperties?.colormaps]);
1329
+ }, [activeDisplaySetInstanceUID, viewportDisplaySets, colorbarProperties?.colormaps, viewport]);
1343
1330
 
1344
1331
  // 3D volume rendering functions
1345
1332
  const setVolumeRenderingPreset = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(preset => {
@@ -1405,7 +1392,10 @@ function useViewportRendering(viewportId, options) {
1405
1392
  setWindowLevel,
1406
1393
  setVOIRange,
1407
1394
  voiRange,
1408
- windowLevel: _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.utilities.windowLevel.toWindowLevel(voiRange?.lower, voiRange?.upper),
1395
+ windowLevel: voiRange ? _cornerstonejs_core__WEBPACK_IMPORTED_MODULE_3__.utilities.windowLevel.toWindowLevel(voiRange?.lower, voiRange?.upper) : {
1396
+ windowCenter: null,
1397
+ windowWidth: null
1398
+ },
1409
1399
  // Colorbar functions
1410
1400
  hasColorbar,
1411
1401
  toggleColorbar,
@@ -1473,10 +1463,10 @@ function getCustomizationData(customizationService) {
1473
1463
  };
1474
1464
  }
1475
1465
 
1476
- /***/ }),
1466
+ /***/ },
1477
1467
 
1478
- /***/ 79063:
1479
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1468
+ /***/ 79063
1469
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
1480
1470
 
1481
1471
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
1482
1472
  /* harmony export */ L: () => (/* binding */ useViewportSegmentations)
@@ -1494,7 +1484,8 @@ const excludedModalities = ['SM', 'OT', 'DOC', 'ECG'];
1494
1484
  function mapSegmentationToDisplay(segmentation, customizationService) {
1495
1485
  const {
1496
1486
  label,
1497
- segments
1487
+ segments,
1488
+ fallbackLabel
1498
1489
  } = segmentation;
1499
1490
 
1500
1491
  // Get the readable text mapping once
@@ -1555,6 +1546,7 @@ function mapSegmentationToDisplay(segmentation, customizationService) {
1555
1546
  return {
1556
1547
  ...segmentation,
1557
1548
  label,
1549
+ fallbackLabel,
1558
1550
  segments: updatedSegments
1559
1551
  };
1560
1552
  }
@@ -1657,74 +1649,36 @@ function useViewportSegmentations({
1657
1649
  return segmentationsWithRepresentations;
1658
1650
  }
1659
1651
 
1660
- /***/ }),
1652
+ /***/ },
1661
1653
 
1662
- /***/ 63081:
1663
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1654
+ /***/ 24688
1655
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
1664
1656
 
1665
- // ESM COMPAT FLAG
1666
- __webpack_require__.r(__webpack_exports__);
1667
1657
 
1668
1658
  // EXPORTS
1669
1659
  __webpack_require__.d(__webpack_exports__, {
1670
- AccordionGroup: () => (/* reexport */ AccordionGroup),
1671
- CloneChildren: () => (/* reexport */ CloneChildren),
1672
- Colorbar: () => (/* reexport */ Colorbar),
1673
- Colormap: () => (/* reexport */ Colormap),
1674
- CornerstoneViewportDownloadForm: () => (/* reexport */ utils_CornerstoneViewportDownloadForm),
1675
- DYNAMIC_VOLUME_LOADER_SCHEME: () => (/* reexport */ DYNAMIC_VOLUME_LOADER_SCHEME),
1676
- DicomUpload: () => (/* reexport */ DicomUpload_DicomUpload),
1677
- Enums: () => (/* reexport */ enums),
1678
- ImageOverlayViewerTool: () => (/* reexport */ tools_ImageOverlayViewerTool),
1679
- MeasumentsMenu: () => (/* reexport */ MeasumentsMenu),
1680
- MeasurementOrAdditionalFindingSets: () => (/* reexport */ MeasurementOrAdditionalFindingSets),
1681
- MeasurementsOrAdditionalFindings: () => (/* reexport */ MeasurementsOrAdditionalFindings),
1682
- OHIFCornerstoneViewport: () => (/* binding */ OHIFCornerstoneViewport),
1683
- PanelMeasurement: () => (/* reexport */ PanelMeasurement),
1684
- PanelSegmentation: () => (/* reexport */ PanelSegmentation),
1685
- PlanarFreehandROI: () => (/* reexport */ measurementServiceMappings_PlanarFreehandROI),
1686
- RectangleROI: () => (/* reexport */ measurementServiceMappings_RectangleROI),
1687
- SeriesMeasurementTrigger: () => (/* reexport */ SeriesMeasurementTrigger),
1688
- SeriesMeasurements: () => (/* reexport */ SeriesMeasurements),
1689
- StudyMeasurements: () => (/* reexport */ StudyMeasurements),
1690
- StudyMeasurementsActions: () => (/* reexport */ StudyMeasurementsActions),
1691
- StudySummaryFromMetadata: () => (/* reexport */ StudySummaryFromMetadata),
1692
- Types: () => (/* reexport */ types_namespaceObject),
1693
- VOLUME_LOADER_SCHEME: () => (/* reexport */ VOLUME_LOADER_SCHEME),
1694
- VolumeLighting: () => (/* reexport */ VolumeLighting),
1695
- VolumeRenderingOptions: () => (/* reexport */ VolumeRenderingOptions),
1696
- VolumeRenderingPresets: () => (/* reexport */ VolumeRenderingPresets),
1697
- VolumeRenderingQuality: () => (/* reexport */ VolumeRenderingQuality),
1698
- VolumeShade: () => (/* reexport */ VolumeShade),
1699
- VolumeShift: () => (/* reexport */ VolumeShift),
1700
- WindowLevel: () => (/* reexport */ WindowLevel),
1701
- WindowLevelActionMenu: () => (/* reexport */ WindowLevelActionMenu),
1702
- WindowLevelActionMenuContent: () => (/* reexport */ WindowLevelActionMenuContent),
1703
- WindowLevelActionMenuWrapper: () => (/* reexport */ WindowLevelActionMenuWrapper),
1660
+ _I: () => (/* reexport */ AccordionGroup),
1661
+ fX: () => (/* reexport */ enums),
1662
+ CP: () => (/* reexport */ MeasurementsOrAdditionalFindings),
1663
+ R9: () => (/* binding */ OHIFCornerstoneViewport),
1664
+ re: () => (/* reexport */ PanelMeasurement),
1665
+ rE: () => (/* reexport */ PanelSegmentation),
1666
+ V: () => (/* reexport */ SeriesMeasurements),
1667
+ B9: () => (/* reexport */ StudyMeasurements),
1668
+ _9: () => (/* reexport */ StudyMeasurementsActions),
1669
+ x3: () => (/* reexport */ StudySummaryFromMetadata),
1670
+ Rj: () => (/* reexport */ VOLUME_LOADER_SCHEME),
1704
1671
  "default": () => (/* binding */ cornerstone_src),
1705
- dicomLoaderService: () => (/* reexport */ utils_dicomLoaderService),
1706
- findNearbyToolData: () => (/* reexport */ findNearbyToolData),
1707
- getActiveViewportEnabledElement: () => (/* reexport */ getActiveViewportEnabledElement),
1708
- getEnabledElement: () => (/* reexport */ state/* getEnabledElement */.kJ),
1709
- getSOPInstanceAttributes: () => (/* reexport */ getSOPInstanceAttributes),
1710
- groupByDisplaySet: () => (/* reexport */ groupByDisplaySet),
1711
- groupByNamedSets: () => (/* reexport */ groupByNamedSets),
1712
- groupByStudy: () => (/* reexport */ groupByStudy),
1713
- measurementMappingUtils: () => (/* reexport */ utils_namespaceObject),
1714
- setEnabledElement: () => (/* reexport */ state/* setEnabledElement */.ye),
1715
- toolNames: () => (/* reexport */ toolNames),
1716
- useActiveViewportSegmentationRepresentations: () => (/* reexport */ useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c),
1717
- useLutPresentationStore: () => (/* reexport */ useLutPresentationStore/* useLutPresentationStore */.I),
1718
- useMeasurementTracking: () => (/* reexport */ useMeasurementTracking/* useMeasurementTracking */.R),
1719
- useMeasurements: () => (/* reexport */ useMeasurements/* useMeasurements */.d),
1720
- usePositionPresentationStore: () => (/* reexport */ usePositionPresentationStore/* usePositionPresentationStore */.q),
1721
- useSegmentationPresentationStore: () => (/* reexport */ useSegmentationPresentationStore/* useSegmentationPresentationStore */.v),
1722
- useSegmentations: () => (/* reexport */ useSegmentations/* useSegmentations */.j),
1723
- useSelectedSegmentationsForViewportStore: () => (/* reexport */ useSelectedSegmentationsForViewportStore),
1724
- useSynchronizersStore: () => (/* reexport */ useSynchronizersStore/* useSynchronizersStore */.U),
1725
- utils: () => (/* reexport */ src_utils)
1672
+ HA: () => (/* reexport */ utils_dicomLoaderService),
1673
+ J4: () => (/* reexport */ getSOPInstanceAttributes),
1674
+ c3: () => (/* reexport */ useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c),
1675
+ qu: () => (/* reexport */ usePositionPresentationStore/* usePositionPresentationStore */.q),
1676
+ jo: () => (/* reexport */ useSegmentations/* useSegmentations */.j),
1677
+ Wp: () => (/* reexport */ src_utils)
1726
1678
  });
1727
1679
 
1680
+ // UNUSED EXPORTS: CloneChildren, Colorbar, Colormap, CornerstoneViewportDownloadForm, DYNAMIC_VOLUME_LOADER_SCHEME, DicomUpload, ImageOverlayViewerTool, MeasumentsMenu, MeasurementOrAdditionalFindingSets, PlanarFreehandROI, RectangleROI, SeriesMeasurementTrigger, Types, VolumeLighting, VolumeRenderingOptions, VolumeRenderingPresets, VolumeRenderingQuality, VolumeShade, VolumeShift, WindowLevel, WindowLevelActionMenu, WindowLevelActionMenuContent, WindowLevelActionMenuWrapper, findNearbyToolData, getActiveViewportEnabledElement, getEnabledElement, groupByDisplaySet, groupByNamedSets, groupByStudy, measurementMappingUtils, setEnabledElement, toolNames, useLutPresentationStore, useMeasurementTracking, useMeasurements, useSegmentationPresentationStore, useSelectedSegmentationsForViewportStore, useSynchronizersStore
1681
+
1728
1682
  // NAMESPACE OBJECT: ../../../extensions/cornerstone/src/enums.ts
1729
1683
  var enums_namespaceObject = {};
1730
1684
  __webpack_require__.r(enums_namespaceObject);
@@ -1734,22 +1688,6 @@ __webpack_require__.d(enums_namespaceObject, {
1734
1688
  Ay: () => (enums)
1735
1689
  });
1736
1690
 
1737
- // NAMESPACE OBJECT: ../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/index.ts
1738
- var utils_namespaceObject = {};
1739
- __webpack_require__.r(utils_namespaceObject);
1740
- __webpack_require__.d(utils_namespaceObject, {
1741
- getDisplayUnit: () => (utils_getDisplayUnit),
1742
- getFirstAnnotationSelected: () => (getFirstAnnotationSelected),
1743
- getHandlesFromPoints: () => (getHandlesFromPoints),
1744
- getSOPInstanceAttributes: () => (getSOPInstanceAttributes),
1745
- isAnnotationSelected: () => (isAnnotationSelected),
1746
- setAnnotationSelected: () => (setAnnotationSelected)
1747
- });
1748
-
1749
- // NAMESPACE OBJECT: ../../../extensions/cornerstone/src/types/index.ts
1750
- var types_namespaceObject = {};
1751
- __webpack_require__.r(types_namespaceObject);
1752
-
1753
1691
  // EXTERNAL MODULE: ../../../node_modules/react/index.js
1754
1692
  var react = __webpack_require__(86326);
1755
1693
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 1 modules
@@ -1770,8 +1708,8 @@ var src = __webpack_require__(42356);
1770
1708
  var loaders = __webpack_require__(19742);
1771
1709
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/enums/RequestType.js
1772
1710
  var RequestType = __webpack_require__(43213);
1773
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/dicom-image-loader/dist/esm/index.js + 77 modules
1774
- var dicom_image_loader_dist_esm = __webpack_require__(75524);
1711
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/dicom-image-loader/dist/esm/index.js + 80 modules
1712
+ var dicom_image_loader_dist_esm = __webpack_require__(76318);
1775
1713
  ;// ../../../extensions/cornerstone/src/initWADOImageLoader.js
1776
1714
 
1777
1715
 
@@ -1913,7 +1851,7 @@ function onCompletedCalibrationLine(servicesManager, csToolsEvent) {
1913
1851
  reject('UIDialogService is not initiated');
1914
1852
  return;
1915
1853
  }
1916
- (0,default_src.callInputDialog)({
1854
+ (0,default_src/* callInputDialog */.l5)({
1917
1855
  uiDialogService,
1918
1856
  title: 'Calibration',
1919
1857
  placeholder: 'Actual Physical distance (mm)',
@@ -2614,6 +2552,7 @@ function getHandlesFromPoints(points) {
2614
2552
  }), {});
2615
2553
  }
2616
2554
  ;// ../../../extensions/cornerstone/src/utils/measurementServiceMappings/utils/selection.ts
2555
+ /* unused harmony import specifier */ var cs3dToolAnnotationUtils;
2617
2556
 
2618
2557
 
2619
2558
  /**
@@ -2622,7 +2561,7 @@ function getHandlesFromPoints(points) {
2622
2561
  * @returns boolean
2623
2562
  */
2624
2563
  function isAnnotationSelected(annotationUID) {
2625
- return dist_esm.annotation.selection.isAnnotationSelected(annotationUID);
2564
+ return cs3dToolAnnotationUtils.selection.isAnnotationSelected(annotationUID);
2626
2565
  }
2627
2566
 
2628
2567
  /**
@@ -2634,7 +2573,7 @@ function setAnnotationSelected(annotationUID, selected) {
2634
2573
  const isCurrentSelected = isAnnotationSelected(annotationUID);
2635
2574
  // branch cut, avoid invoking imaging library unnecessarily.
2636
2575
  if (isCurrentSelected !== selected) {
2637
- dist_esm.annotation.selection.setAnnotationSelected(annotationUID, selected);
2576
+ cs3dToolAnnotationUtils.selection.setAnnotationSelected(annotationUID, selected);
2638
2577
  }
2639
2578
  }
2640
2579
  function getFirstAnnotationSelected(element) {
@@ -6065,6 +6004,12 @@ const connectMeasurementServiceToTools = ({
6065
6004
  if (source?.name && source.name !== initMeasurementService_CORNERSTONE_3D_TOOLS_SOURCE_NAME) {
6066
6005
  return;
6067
6006
  }
6007
+ // Cancel any active tool manipulation (e.g., Spline/Livewire) to avoid leaving the tool
6008
+ // in a drawing state after deleting a not completed measurement, which can block viewport interactivity.
6009
+ const element = getActiveViewportEnabledElement(viewportGridService)?.viewport?.element;
6010
+ if (element) {
6011
+ (0,dist_esm.cancelActiveManipulations)(element);
6012
+ }
6068
6013
  const removedAnnotation = dist_esm.annotation.state.getAnnotation(removedMeasurementId);
6069
6014
  removeAnnotation(removedMeasurementId);
6070
6015
  // Ensure `removedAnnotation` is available before triggering the memo,
@@ -7463,7 +7408,8 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
7463
7408
  'viewportOverlay.topRight': [],
7464
7409
  'viewportOverlay.bottomLeft': [{
7465
7410
  id: 'WindowLevel',
7466
- inheritsFrom: 'ohif.overlayItem.windowLevel'
7411
+ inheritsFrom: 'ohif.overlayItem.windowLevel',
7412
+ title: 'Window Level'
7467
7413
  }, {
7468
7414
  id: 'ZoomLevel',
7469
7415
  inheritsFrom: 'ohif.overlayItem.zoomLevel',
@@ -7474,11 +7420,12 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
7474
7420
  }],
7475
7421
  'viewportOverlay.bottomRight': [{
7476
7422
  id: 'InstanceNumber',
7477
- inheritsFrom: 'ohif.overlayItem.instanceNumber'
7423
+ inheritsFrom: 'ohif.overlayItem.instanceNumber',
7424
+ title: 'Instance Number'
7478
7425
  }]
7479
7426
  });
7480
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3075 modules
7481
- var ui_next_src = __webpack_require__(12517);
7427
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3076 modules
7428
+ var ui_next_src = __webpack_require__(2343);
7482
7429
  // EXTERNAL MODULE: ../../../node_modules/react-i18next/dist/es/index.js + 15 modules
7483
7430
  var es = __webpack_require__(99993);
7484
7431
  ;// ../../../extensions/cornerstone/src/components/ExportSegmentationSubMenuItem.tsx
@@ -7501,37 +7448,13 @@ const ExportSegmentationSubMenuItem = ({
7501
7448
  className: "text-foreground"
7502
7449
  }), /*#__PURE__*/react.createElement("span", {
7503
7450
  className: "pl-2"
7504
- }, t('Download & Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuPortal */.dce, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubContent */.M56, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
7505
- className: "flex items-center pl-0"
7506
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Download, {
7507
- className: "h-5 w-5"
7508
- }), /*#__PURE__*/react.createElement("span", {
7509
- className: "pl-1"
7510
- }, t('Download'))), segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7451
+ }, t('Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuPortal */.dce, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubContent */.M56, null, segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7511
7452
  onClick: e => {
7512
7453
  e.preventDefault();
7513
7454
  actions.downloadCSVSegmentationReport(segmentationId);
7514
7455
  },
7515
7456
  disabled: !allowExport
7516
7457
  }, t('CSV Report')), segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7517
- onClick: e => {
7518
- e.preventDefault();
7519
- actions.onSegmentationDownload(segmentationId);
7520
- },
7521
- disabled: !allowExport
7522
- }, t('DICOM SEG')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7523
- onClick: e => {
7524
- e.preventDefault();
7525
- actions.onSegmentationDownloadRTSS(segmentationId);
7526
- },
7527
- disabled: !allowExport
7528
- }, t('DICOM RTSS')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
7529
- className: "flex items-center pl-0"
7530
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7531
- className: "h-5 w-5"
7532
- }), /*#__PURE__*/react.createElement("span", {
7533
- className: "pl-1 pt-1"
7534
- }, t('Export'))), segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7535
7458
  onClick: e => {
7536
7459
  e.preventDefault();
7537
7460
  actions.storeSegmentation(segmentationId, 'SEG');
@@ -7608,16 +7531,6 @@ const CustomDropdownMenuContent = () => {
7608
7531
  context: 'CORNERSTONE'
7609
7532
  });
7610
7533
  },
7611
- onSegmentationDownloadRTSS: segmentationId => {
7612
- commandsManager.run('downloadRTSS', {
7613
- segmentationId
7614
- });
7615
- },
7616
- onSegmentationDownload: segmentationId => {
7617
- commandsManager.run('downloadSegmentation', {
7618
- segmentationId
7619
- });
7620
- },
7621
7534
  downloadCSVSegmentationReport: segmentationId => {
7622
7535
  commandsManager.run('downloadCSVSegmentationReport', {
7623
7536
  segmentationId
@@ -7815,7 +7728,7 @@ function SegmentationToolConfig() {
7815
7728
  });
7816
7729
  };
7817
7730
  return /*#__PURE__*/react.createElement("div", {
7818
- className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-black px-2 py-3"
7731
+ className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-background px-2 py-3"
7819
7732
  }, /*#__PURE__*/react.createElement("div", {
7820
7733
  className: "flex items-center gap-2"
7821
7734
  }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
@@ -8624,7 +8537,7 @@ const DicomUploadProgressItem = /*#__PURE__*/(0,react.memo)(({
8624
8537
  }, /*#__PURE__*/react.createElement("div", {
8625
8538
  className: "flex w-6 shrink-0 items-center justify-center"
8626
8539
  }, getStatusIcon()), /*#__PURE__*/react.createElement("div", {
8627
- className: "overflow-hidden text-ellipsis whitespace-nowrap text-white"
8540
+ className: "text-foreground overflow-hidden text-ellipsis whitespace-nowrap"
8628
8541
  }, dicomFileUploader.getFileName())), failedReason && /*#__PURE__*/react.createElement("div", {
8629
8542
  className: "pl-10"
8630
8543
  }, failedReason)), /*#__PURE__*/react.createElement("div", {
@@ -8866,7 +8779,7 @@ function DicomUploadProgress({
8866
8779
  }, [numFilesCompleted]);
8867
8780
  const getNumCompletedAndTimeRemainingComponent = () => {
8868
8781
  return /*#__PURE__*/react.createElement("div", {
8869
- className: "bg-muted flex h-14 items-center px-1 pb-4 text-lg text-white"
8782
+ className: "bg-muted text-foreground flex h-14 items-center px-1 pb-4 text-lg"
8870
8783
  }, numFilesCompleted === dicomFileUploaderArr.length ? /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("span", {
8871
8784
  className: NO_WRAP_ELLIPSIS_CLASS_NAMES
8872
8785
  }, `${dicomFileUploaderArr.length} ${dicomFileUploaderArr.length > 1 ? 'files' : 'file'} completed.`), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
@@ -8916,7 +8829,7 @@ function DicomUploadProgress({
8916
8829
  return /*#__PURE__*/react.createElement("div", {
8917
8830
  className: "flex grow flex-col"
8918
8831
  }, getNumCompletedAndTimeRemainingComponent(), /*#__PURE__*/react.createElement("div", {
8919
- className: "flex grow flex-col overflow-hidden bg-black text-lg"
8832
+ className: "flex grow flex-col overflow-hidden bg-background text-lg"
8920
8833
  }, getPercentCompleteComponent(), /*#__PURE__*/react.createElement("div", {
8921
8834
  className: "ohif-scrollbar h-1 grow overflow-y-scroll px-2"
8922
8835
  }, dicomFileUploaderArr.filter(dicomFileUploader => !showFailedOnly || dicomFileUploader.getStatus() === UploadStatus.Failed).map(dicomFileUploader => /*#__PURE__*/react.createElement(DicomUpload_DicomUploadProgressItem, {
@@ -8945,7 +8858,7 @@ function DicomUpload({
8945
8858
  onComplete,
8946
8859
  onStarted
8947
8860
  }) {
8948
- const baseClassNames = 'min-h-[375px] flex flex-col bg-black select-none rounded-lg overflow-hidden';
8861
+ const baseClassNames = 'min-h-[375px] flex flex-col bg-background select-none rounded-lg overflow-hidden';
8949
8862
  const [dicomFileUploaderArr, setDicomFileUploaderArr] = (0,react.useState)([]);
8950
8863
  const onDrop = (0,react.useCallback)(async acceptedFiles => {
8951
8864
  onStarted();
@@ -9067,7 +8980,8 @@ function ViewportDownloadFormNew({
9067
8980
  onDimensionsChange,
9068
8981
  onEnableViewport,
9069
8982
  onDisableViewport,
9070
- onDownload
8983
+ onDownload,
8984
+ onCopyToClipboard
9071
8985
  }) {
9072
8986
  const [viewportElement, setViewportElement] = (0,react.useState)(null);
9073
8987
  const [showWarningMessage, setShowWarningMessage] = (0,react.useState)(true);
@@ -9094,7 +9008,7 @@ function ViewportDownloadFormNew({
9094
9008
  "data-viewport-uid": viewportId,
9095
9009
  ref: setViewportElement
9096
9010
  }, warningState.enabled && showWarningMessage && /*#__PURE__*/react.createElement("div", {
9097
- className: "text-foreground absolute left-1/2 bottom-[5px] z-[1000] -translate-x-1/2 whitespace-nowrap rounded bg-black p-3 text-xs font-bold",
9011
+ className: "text-foreground absolute left-1/2 bottom-[5px] z-[1000] -translate-x-1/2 whitespace-nowrap rounded bg-background p-3 text-xs font-bold",
9098
9012
  style: {
9099
9013
  fontSize: '12px'
9100
9014
  }
@@ -9140,12 +9054,23 @@ function ViewportDownloadFormNew({
9140
9054
  className: "mt-2"
9141
9055
  }, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Right, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
9142
9056
  onClick: onClose
9143
- }, t('Common:Cancel')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Primary, {
9057
+ }, t('Common:Cancel')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
9058
+ onClick: async () => {
9059
+ try {
9060
+ await onCopyToClipboard();
9061
+ ui_next_src/* toast */.oRP.success(t('Image copied to clipboard'));
9062
+ onClose();
9063
+ } catch (error) {
9064
+ ui_next_src/* toast */.oRP.error(t('Failed to copy image to clipboard'));
9065
+ console.error('Failed to copy to clipboard:', error);
9066
+ }
9067
+ }
9068
+ }, t('Copy to Clipboard')), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Primary, {
9144
9069
  onClick: () => {
9145
9070
  onDownload(filename || DEFAULT_FILENAME, fileType);
9146
9071
  onClose();
9147
9072
  }
9148
- }, t('Common:Save')))))));
9073
+ }, t('Save Image')))))));
9149
9074
  }
9150
9075
  /* harmony default export */ const captureViewportModalCustomization = ({
9151
9076
  'ohif.captureViewportModal': ViewportDownloadFormNew
@@ -9563,17 +9488,39 @@ const CornerstoneViewportDownloadForm = ({
9563
9488
  } = activeViewportEnabledElement;
9564
9489
  const downloadViewport = renderingEngine.getViewport(VIEWPORT_ID);
9565
9490
  try {
9491
+ // Capture current viewport state
9492
+ // - properties: VOI, colormap, interpolation, etc.
9493
+ // - viewPresentation: flip/rotate/zoom presentation state added for
9494
+ // saving flip and rotation for capture
9495
+ // - viewReference: image/volume reference
9496
+ const properties = viewport.getProperties();
9497
+ const viewPresentation = viewport.getViewPresentation?.();
9498
+ const viewRef = viewport.getViewReference?.();
9566
9499
  if (downloadViewport instanceof esm.StackViewport) {
9567
9500
  const imageId = viewport.getCurrentImageId();
9568
- const properties = viewport.getProperties();
9569
9501
  await downloadViewport.setStack([imageId]);
9570
- downloadViewport.setProperties(properties);
9571
9502
  } else if (downloadViewport instanceof esm.BaseVolumeViewport) {
9572
9503
  const volumeIds = viewport.getAllVolumeIds();
9573
- downloadViewport.setVolumes([{
9504
+ await downloadViewport.setVolumes([{
9574
9505
  volumeId: volumeIds[0]
9575
9506
  }]);
9576
9507
  }
9508
+
9509
+ // Apply presentation state so captured image preserves flip/rotate
9510
+ if (viewPresentation && downloadViewport.setViewPresentation) {
9511
+ downloadViewport.setViewPresentation(viewPresentation);
9512
+ }
9513
+
9514
+ // Apply viewport display properties
9515
+ downloadViewport.setProperties(properties);
9516
+
9517
+ // Ensure correct image/volume reference
9518
+ if (viewRef && downloadViewport.setViewReference) {
9519
+ downloadViewport.setViewReference(viewRef);
9520
+ }
9521
+ downloadViewport.render();
9522
+
9523
+ // Re-apply segmentation overlays to the download viewport
9577
9524
  if (segmentationRepresentations?.length) {
9578
9525
  segmentationRepresentations.forEach(segRepresentation => {
9579
9526
  const {
@@ -9667,6 +9614,36 @@ const CornerstoneViewportDownloadForm = ({
9667
9614
  filename
9668
9615
  });
9669
9616
  };
9617
+ const handleCopyToClipboard = async () => {
9618
+ const divForDownloadViewport = document.querySelector(`div[data-viewport-uid="${VIEWPORT_ID}"]`);
9619
+ if (!divForDownloadViewport) {
9620
+ console.debug('No viewport found for copy');
9621
+ return;
9622
+ }
9623
+ try {
9624
+ const canvas = await (0,html2canvas_esm/* default */.A)(divForDownloadViewport);
9625
+
9626
+ // Clipboard API only supports PNG format in most browsers
9627
+ const blob = await new Promise((resolve, reject) => {
9628
+ canvas.toBlob(blob => {
9629
+ if (blob) {
9630
+ resolve(blob);
9631
+ } else {
9632
+ reject(new Error('Failed to create blob from canvas'));
9633
+ }
9634
+ }, 'image/png', 1.0);
9635
+ });
9636
+
9637
+ // Copy to clipboard using the Clipboard API
9638
+ await navigator.clipboard.write([new ClipboardItem({
9639
+ 'image/png': blob
9640
+ })]);
9641
+ console.log('Image copied to clipboard successfully');
9642
+ } catch (error) {
9643
+ console.error('Failed to copy image to clipboard:', error);
9644
+ throw error;
9645
+ }
9646
+ };
9670
9647
  const ViewportDownloadFormNew = customizationService.getCustomization('ohif.captureViewportModal');
9671
9648
  return /*#__PURE__*/react.createElement(ViewportDownloadFormNew, {
9672
9649
  onClose: hide,
@@ -9680,6 +9657,7 @@ const CornerstoneViewportDownloadForm = ({
9680
9657
  onEnableViewport: handleEnableViewport,
9681
9658
  onDisableViewport: handleDisableViewport,
9682
9659
  onDownload: handleDownload,
9660
+ onCopyToClipboard: handleCopyToClipboard,
9683
9661
  warningState: warningState
9684
9662
  });
9685
9663
  };
@@ -10756,11 +10734,26 @@ function commandsModule({
10756
10734
  segmentIndex: targetIndex
10757
10735
  } = targetSegmentation;
10758
10736
 
10737
+ // Check if the segment has voxels before computing bidirectional measurement
10738
+ const uniqueSegmentIndices = dist_esm.utilities.segmentation.getUniqueSegmentIndices(targetId);
10739
+ const hasVoxels = uniqueSegmentIndices.includes(targetIndex);
10740
+ if (!hasVoxels) {
10741
+ uiNotificationService.show({
10742
+ title: i18n_src/* default */.A.t('SegmentationPanel:Segment Bidirectional'),
10743
+ message: i18n_src/* default */.A.t('SegmentationPanel:Draw a segment before using bidirectional measurement'),
10744
+ type: 'warning'
10745
+ });
10746
+ return;
10747
+ }
10748
+
10759
10749
  // Get bidirectional measurement data
10760
10750
  const bidirectionalData = await dist_esm.utilities.segmentation.getSegmentLargestBidirectional({
10761
10751
  segmentationId: targetId,
10762
10752
  segmentIndices: [targetIndex]
10763
10753
  });
10754
+ if (!bidirectionalData.length) {
10755
+ return;
10756
+ }
10764
10757
  const activeViewportId = viewportGridService.getActiveViewportId();
10765
10758
 
10766
10759
  // Process each bidirectional measurement
@@ -10962,7 +10955,7 @@ function commandsModule({
10962
10955
  return;
10963
10956
  }
10964
10957
  if (!labelConfig) {
10965
- const label = await (0,default_src.callInputDialog)({
10958
+ const label = await (0,default_src/* callInputDialog */.l5)({
10966
10959
  uiDialogService,
10967
10960
  title: i18n_src/* default */.A.t('Tools:Edit Measurement Label'),
10968
10961
  placeholder: measurement.label || i18n_src/* default */.A.t('Tools:Enter new label'),
@@ -10976,7 +10969,7 @@ function commandsModule({
10976
10969
  }
10977
10970
  return;
10978
10971
  }
10979
- const val = await (0,default_src.callInputDialogAutoComplete)({
10972
+ const val = await (0,default_src/* callInputDialogAutoComplete */.fq)({
10980
10973
  measurement,
10981
10974
  uiDialogService,
10982
10975
  labelConfig,
@@ -11196,7 +11189,7 @@ function commandsModule({
11196
11189
  const labelConfig = customizationService.getCustomization('measurementLabels');
11197
11190
  const renderContent = customizationService.getCustomization('ui.labellingComponent');
11198
11191
  if (!labelConfig) {
11199
- const label = await (0,default_src.callInputDialog)({
11192
+ const label = await (0,default_src/* callInputDialog */.l5)({
11200
11193
  uiDialogService,
11201
11194
  title: i18n_src/* default */.A.t('Tools:Edit Arrow Text'),
11202
11195
  placeholder: data?.data?.label || i18n_src/* default */.A.t('Tools:Enter new text'),
@@ -11205,7 +11198,7 @@ function commandsModule({
11205
11198
  callback?.(label);
11206
11199
  return;
11207
11200
  }
11208
- const value = await (0,default_src.callInputDialogAutoComplete)({
11201
+ const value = await (0,default_src/* callInputDialogAutoComplete */.fq)({
11209
11202
  uiDialogService,
11210
11203
  labelConfig,
11211
11204
  renderContent
@@ -12101,7 +12094,7 @@ function commandsModule({
12101
12094
  segmentationService,
12102
12095
  viewportGridService
12103
12096
  } = servicesManager.services;
12104
- const displaySetInstanceUIDs = await (0,default_src.createReportAsync)({
12097
+ const displaySetInstanceUIDs = await (0,default_src/* createReportAsync */.Vy)({
12105
12098
  servicesManager,
12106
12099
  getReport: () => commandsManager.runCommand('storeSegmentation', args),
12107
12100
  reportType: 'Segmentation'
@@ -12178,14 +12171,15 @@ function commandsModule({
12178
12171
  * @param props.segmentationId - The ID of the segmentation to remove
12179
12172
  */
12180
12173
  removeSegmentationFromViewportCommand: ({
12181
- segmentationId
12174
+ segmentationId: displaySetInstanceUID
12182
12175
  }) => {
12183
12176
  const {
12184
- segmentationService,
12185
12177
  viewportGridService
12186
12178
  } = servicesManager.services;
12187
- segmentationService.removeSegmentationRepresentations(viewportGridService.getActiveViewportId(), {
12188
- segmentationId
12179
+ const viewportId = viewportGridService.getActiveViewportId();
12180
+ commandsManager.runCommand('removeDisplaySetLayer', {
12181
+ viewportId,
12182
+ displaySetInstanceUID
12189
12183
  });
12190
12184
  },
12191
12185
  /**
@@ -12213,7 +12207,7 @@ function commandsModule({
12213
12207
  return;
12214
12208
  }
12215
12209
  const segment = segmentation.segments[segmentIndex];
12216
- (0,default_src.callInputDialog)({
12210
+ (0,default_src/* callInputDialog */.l5)({
12217
12211
  uiDialogService,
12218
12212
  title: i18n_src/* default */.A.t('Tools:Edit Segment Label'),
12219
12213
  placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
@@ -12236,7 +12230,7 @@ function commandsModule({
12236
12230
  const {
12237
12231
  label
12238
12232
  } = segmentation;
12239
- (0,default_src.callInputDialog)({
12233
+ (0,default_src/* callInputDialog */.l5)({
12240
12234
  uiDialogService,
12241
12235
  title: i18n_src/* default */.A.t('Tools:Edit Segmentation Label'),
12242
12236
  placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
@@ -12266,7 +12260,7 @@ function commandsModule({
12266
12260
  a: color[3] / 255.0
12267
12261
  };
12268
12262
  uiDialogService.show({
12269
- content: default_src.colorPickerDialog,
12263
+ content: default_src/* colorPickerDialog */.wS,
12270
12264
  title: i18n_src/* default */.A.t('Tools:Segment Color'),
12271
12265
  contentProps: {
12272
12266
  value: rgbaColor,
@@ -15342,6 +15336,9 @@ function ViewportDataOverlayMenu({
15342
15336
  } = (0,useViewportDisplaySets/* useViewportDisplaySets */.N)(viewportId);
15343
15337
  const [optimisticOverlayDisplaySets, setOptimisticOverlayDisplaySets] = (0,react.useState)(overlayDisplaySets);
15344
15338
  const [thresholdOpacityEnabled, setThresholdOpacityEnabled] = (0,react.useState)(false);
15339
+ (0,react.useEffect)(() => {
15340
+ setOptimisticOverlayDisplaySets(overlayDisplaySets);
15341
+ }, [backgroundDisplaySet?.displaySetInstanceUID, overlayDisplaySets]);
15345
15342
 
15346
15343
  /**
15347
15344
  * Change the background display set
@@ -15648,7 +15645,8 @@ function ViewportDataOverlayMenu({
15648
15645
  }
15649
15646
  }
15650
15647
  }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
15651
- className: "flex-1"
15648
+ className: "flex-1",
15649
+ "data-cy": `overlay-background-ds-select-${viewportId}`
15652
15650
  }, /*#__PURE__*/react.createElement(ui_next_src/* SelectValue */.yvm, null, (backgroundDisplaySet?.SeriesDescription || backgroundDisplaySet?.label || 'background').toUpperCase())), /*#__PURE__*/react.createElement(ui_next_src/* SelectContent */.gCo, null, potentialBackgroundDisplaySets.map(displaySet => /*#__PURE__*/react.createElement(ui_next_src/* SelectItem */.ebT, {
15653
15651
  key: displaySet.displaySetInstanceUID,
15654
15652
  value: displaySet.displaySetInstanceUID,
@@ -15923,7 +15921,7 @@ function ViewportOrientationMenu({
15923
15921
  }) : null), /*#__PURE__*/react.createElement("div", {
15924
15922
  className: "flex-1 text-left"
15925
15923
  }, "Acquisition")), /*#__PURE__*/react.createElement("div", {
15926
- className: "mx-1 my-2 border-t border-white/20"
15924
+ className: "border-input mx-1 my-2 border-t"
15927
15925
  }), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
15928
15926
  variant: "ghost",
15929
15927
  className: "flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0",
@@ -16264,7 +16262,7 @@ function VolumeRenderingPresetsContent({
16264
16262
  }
16265
16263
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.ByName, {
16266
16264
  name: preset.name,
16267
- className: selectedPreset?.name === preset.name ? 'border-highlight h-[75px] w-[95px] max-w-none rounded border-2' : 'hover:border-highlight h-[75px] w-[95px] max-w-none rounded border-2 border-black'
16265
+ className: selectedPreset?.name === preset.name ? 'border-highlight h-[75px] w-[95px] max-w-none rounded border-2' : 'hover:border-highlight h-[75px] w-[95px] max-w-none rounded border-2 border-background'
16268
16266
  }), /*#__PURE__*/react.createElement("label", {
16269
16267
  className: "text-muted-foreground mt-1 text-left text-xs"
16270
16268
  }, formatLabel(preset.name, 11)))))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, {
@@ -17410,9 +17408,9 @@ function ModalityLoadBadge({
17410
17408
  if (!statusInfo.isHydrated) {
17411
17409
  return /*#__PURE__*/react.createElement("div", {
17412
17410
  "data-cy": `ModalityLoadBadge-${viewportId}`,
17413
- className: "flex h-6 cursor-default text-sm leading-6 text-white"
17411
+ className: "text-foreground flex h-6 cursor-default text-sm leading-6"
17414
17412
  }, /*#__PURE__*/react.createElement("div", {
17415
- className: "bg-customgray-100 flex min-w-[45px] items-center rounded-l-xl rounded-r p-1"
17413
+ className: "bg-popover flex min-w-[45px] items-center rounded-l-xl rounded-r p-1"
17416
17414
  }, /*#__PURE__*/react.createElement(StatusIcon, null), /*#__PURE__*/react.createElement("span", {
17417
17415
  className: "ml-1"
17418
17416
  }, statusInfo.type)), statusInfo.type !== 'SR' && /*#__PURE__*/react.createElement(ui_next_src/* ViewportActionButton */.N8H, {
@@ -18829,7 +18827,12 @@ const segmentationRepresentationModifiedCallback = async (synchronizerInstance,
18829
18827
  const sourceDisplaySetUIDs = extractDisplaySetUIDs(sourceViewportInfo);
18830
18828
  const targetDisplaySetUIDs = extractDisplaySetUIDs(targetViewportInfo);
18831
18829
  const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs);
18832
- if (!sharedDisplaySetExists && !viewport.getFrameOfReferenceUID()) {
18830
+ const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID();
18831
+ const sourceFrameOfReferenceUID = (0,esm.getEnabledElementByViewportId)(sourceViewportId)?.viewport?.getFrameOfReferenceUID();
18832
+ if (!sharedDisplaySetExists && !targetFrameOfReferenceUID) {
18833
+ return;
18834
+ }
18835
+ if (!sharedDisplaySetExists && targetFrameOfReferenceUID !== sourceFrameOfReferenceUID) {
18833
18836
  return;
18834
18837
  }
18835
18838
  const targetViewportRepresentation = segmentationService.getSegmentationRepresentations(targetViewportId, {
@@ -19196,11 +19199,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
19196
19199
  this.EVENTS = SegmentationService_EVENTS;
19197
19200
  this.destroy = () => {
19198
19201
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
19199
- esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationModifiedFromSource);
19202
+ esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
19200
19203
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
19201
19204
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
19202
19205
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_ADDED, this._onSegmentationRepresentationModifiedFromSource);
19203
- esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationModifiedFromSource);
19206
+ esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
19204
19207
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
19205
19208
  this.reset();
19206
19209
  };
@@ -19261,6 +19264,16 @@ class SegmentationService extends src/* PubSubService */.Rc {
19261
19264
  viewportId
19262
19265
  });
19263
19266
  };
19267
+ this._onSegmentationRepresentationRemovedFromSource = evt => {
19268
+ const {
19269
+ segmentationId,
19270
+ viewportId
19271
+ } = evt.detail;
19272
+ this._broadcastEvent(this.EVENTS.SEGMENTATION_REPRESENTATION_REMOVED, {
19273
+ segmentationId,
19274
+ viewportId
19275
+ });
19276
+ };
19264
19277
  this._onSegmentationModifiedFromSource = evt => {
19265
19278
  const {
19266
19279
  segmentationId
@@ -19277,6 +19290,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
19277
19290
  segmentationId
19278
19291
  });
19279
19292
  };
19293
+ this._onSegmentationRemovedFromSource = evt => {
19294
+ const {
19295
+ segmentationId
19296
+ } = evt.detail;
19297
+ this._broadcastEvent(this.EVENTS.SEGMENTATION_REMOVED, {
19298
+ segmentationId
19299
+ });
19300
+ };
19280
19301
  this._onAnnotationCutMergeProcessCompletedFromSource = evt => {
19281
19302
  const {
19282
19303
  segmentationId
@@ -19482,6 +19503,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19482
19503
  },
19483
19504
  config: {
19484
19505
  label,
19506
+ fallbackLabel: `S:${displaySet.SeriesNumber} ${displaySet.Modality}`,
19485
19507
  segments: options?.segments && Object.keys(options.segments).length > 0 ? options.segments : {
19486
19508
  1: {
19487
19509
  label: `${i18n_src/* default */.A.t('Segment')} 1`,
@@ -19613,6 +19635,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19613
19635
  },
19614
19636
  config: {
19615
19637
  label: segDisplaySet.SeriesDescription,
19638
+ fallbackLabel: `S:${segDisplaySet.SeriesNumber} ${segDisplaySet.Modality}`,
19616
19639
  segments
19617
19640
  }
19618
19641
  };
@@ -19673,7 +19696,8 @@ class SegmentationService extends src/* PubSubService */.Rc {
19673
19696
  }
19674
19697
  },
19675
19698
  config: {
19676
- label: rtDisplaySet.SeriesDescription
19699
+ label: rtDisplaySet.SeriesDescription,
19700
+ fallbackLabel: `S:${rtDisplaySet.SeriesNumber} ${rtDisplaySet.Modality}`
19677
19701
  }
19678
19702
  };
19679
19703
  const segments = {};
@@ -20170,14 +20194,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
20170
20194
  }
20171
20195
  /**
20172
20196
  * Clears segmentation representations from the viewport.
20173
- * Unlike removeSegmentationRepresentations, this doesn't update
20197
+ * Unlike removeRepresentationsFromViewport, this doesn't update
20174
20198
  * removed display set and representation maps.
20175
20199
  * We track removed segmentations manually to avoid re-adding them
20176
20200
  * when the display set is added again.
20177
20201
  * @param viewportId - The viewport ID to clear segmentation representations from.
20178
20202
  */
20179
20203
  clearSegmentationRepresentations(viewportId) {
20180
- this.removeSegmentationRepresentations(viewportId);
20204
+ this.removeRepresentationsFromViewport(viewportId);
20181
20205
  }
20182
20206
 
20183
20207
  /**
@@ -20192,7 +20216,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20192
20216
  }
20193
20217
 
20194
20218
  /**
20195
- * It removes the segmentation representations from the viewport.
20219
+ * Removes segmentation representations from the viewport.
20196
20220
  * @param viewportId - The viewport id to remove the segmentation representations from.
20197
20221
  * @param specifier - The specifier to remove the segmentation representations.
20198
20222
  *
@@ -20202,7 +20226,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20202
20226
  * If a type specifier is provided, only the segmentation representation with the specified type are removed.
20203
20227
  * If both a segmentationId and type specifier are provided, only the segmentation representation with the specified segmentationId and type are removed.
20204
20228
  */
20205
- removeSegmentationRepresentations(viewportId, specifier = {}) {
20229
+ removeRepresentationsFromViewport(viewportId, specifier = {}) {
20206
20230
  dist_esm.segmentation.removeSegmentationRepresentations(viewportId, specifier);
20207
20231
  }
20208
20232
 
@@ -20558,6 +20582,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20558
20582
  id: id,
20559
20583
  segmentationId,
20560
20584
  label: segmentation.label,
20585
+ fallbackLabel: segmentation.fallbackLabel,
20561
20586
  active,
20562
20587
  type,
20563
20588
  visible,
@@ -20570,11 +20595,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
20570
20595
  }
20571
20596
  _initSegmentationService() {
20572
20597
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
20573
- esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationModifiedFromSource);
20598
+ esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
20574
20599
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
20575
20600
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
20576
20601
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_ADDED, this._onSegmentationRepresentationModifiedFromSource);
20577
- esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationModifiedFromSource);
20602
+ esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
20578
20603
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
20579
20604
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, this._onAnnotationCutMergeProcessCompletedFromSource);
20580
20605
  }
@@ -20780,6 +20805,7 @@ const ORTHOGRAPHIC = 'orthographic';
20780
20805
  const VOLUME_3D = 'volume3d';
20781
20806
  const VIDEO = 'video';
20782
20807
  const WHOLESLIDE = 'wholeslide';
20808
+ const ECG = 'ecg';
20783
20809
  function getCornerstoneViewportType(viewportType, displaySets) {
20784
20810
  const lowerViewportType = displaySets?.[0]?.viewportType?.toLowerCase() || viewportType.toLowerCase();
20785
20811
  if (lowerViewportType === STACK) {
@@ -20791,13 +20817,16 @@ function getCornerstoneViewportType(viewportType, displaySets) {
20791
20817
  if (lowerViewportType === WHOLESLIDE) {
20792
20818
  return esm.Enums.ViewportType.WHOLE_SLIDE;
20793
20819
  }
20820
+ if (lowerViewportType === ECG) {
20821
+ return esm.Enums.ViewportType.ECG;
20822
+ }
20794
20823
  if (lowerViewportType === VOLUME || lowerViewportType === ORTHOGRAPHIC) {
20795
20824
  return esm.Enums.ViewportType.ORTHOGRAPHIC;
20796
20825
  }
20797
20826
  if (lowerViewportType === VOLUME_3D) {
20798
20827
  return esm.Enums.ViewportType.VOLUME_3D;
20799
20828
  }
20800
- throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide`);
20829
+ throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide, ecg`);
20801
20830
  }
20802
20831
  ;// ../../../extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts
20803
20832
  var _CornerstoneCacheService;
@@ -22072,6 +22101,15 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22072
22101
  /**
22073
22102
  * Sets the image data for the given viewport.
22074
22103
  */
22104
+ async _setEcgViewport(viewport, viewportData) {
22105
+ const [displaySet] = viewportData.data;
22106
+ const imageId = displaySet.imageIds?.[0];
22107
+ if (!imageId) {
22108
+ console.error('[CornerstoneViewportService] ECG display set has no imageId');
22109
+ return;
22110
+ }
22111
+ return viewport.setEcg(imageId);
22112
+ }
22075
22113
  async _setOtherViewport(viewport, viewportData, viewportInfo, _presentations = {}) {
22076
22114
  const [displaySet] = viewportData.data;
22077
22115
  return viewport.setDataIds(displaySet.imageIds, {
@@ -22140,32 +22178,25 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22140
22178
  if (initialImageIndexToUse === undefined || initialImageIndexToUse === null || initialImageIndexToUse < 0) {
22141
22179
  initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
22142
22180
  }
22143
- return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
22181
+ await viewport.setStack(imageIds, initialImageIndexToUse);
22182
+ viewport.setProperties({
22183
+ ...properties
22184
+ });
22185
+ this.setPresentations(viewport.id, presentations, viewportInfo);
22186
+ await this._addOverlayRepresentations(overlayProcessingResults);
22187
+ if (displayArea) {
22188
+ viewport.setDisplayArea(displayArea);
22189
+ }
22190
+ if (rotation) {
22144
22191
  viewport.setProperties({
22145
- ...properties
22192
+ rotation
22146
22193
  });
22147
- this.setPresentations(viewport.id, presentations, viewportInfo);
22148
- if (overlayProcessingResults?.length) {
22149
- overlayProcessingResults.forEach(overlayProcessingResult => {
22150
- if (overlayProcessingResult?.addOverlayFn) {
22151
- overlayProcessingResult.addOverlayFn();
22152
- }
22153
- });
22154
- }
22155
- if (displayArea) {
22156
- viewport.setDisplayArea(displayArea);
22157
- }
22158
- if (rotation) {
22159
- viewport.setProperties({
22160
- rotation
22161
- });
22162
- }
22163
- if (flipHorizontal) {
22164
- viewport.setCamera({
22165
- flipHorizontal: true
22166
- });
22167
- }
22168
- });
22194
+ }
22195
+ if (flipHorizontal) {
22196
+ viewport.setCamera({
22197
+ flipHorizontal: true
22198
+ });
22199
+ }
22169
22200
  }
22170
22201
  _getInitialImageIndexForViewport(viewportInfo, imageIds) {
22171
22202
  const initialImageOptions = viewportInfo.getInitialImageOptions();
@@ -22389,15 +22420,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22389
22420
  });
22390
22421
  }
22391
22422
  await viewport.setVolumes(volumeInputArray);
22392
- if (overlayProcessingResults?.length) {
22393
- overlayProcessingResults.forEach(({
22394
- addOverlayFn
22395
- }) => {
22396
- if (addOverlayFn) {
22397
- addOverlayFn();
22398
- }
22399
- });
22400
- }
22423
+ await this._addOverlayRepresentations(overlayProcessingResults);
22401
22424
  viewport.render();
22402
22425
  volumesProperties.forEach(({
22403
22426
  properties,
@@ -22460,7 +22483,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22460
22483
  const {
22461
22484
  predecessorImageId
22462
22485
  } = displaySet;
22463
- segmentationService.addSegmentationRepresentation(viewport.id, {
22486
+ const segmentationRepresentationPromise = segmentationService.addSegmentationRepresentation(viewport.id, {
22464
22487
  segmentationId,
22465
22488
  predecessorImageId,
22466
22489
  type: representationType,
@@ -22468,11 +22491,21 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22468
22491
  blendMode: viewport?.getBlendMode?.() === 1 ? dist_esm_enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
22469
22492
  }
22470
22493
  });
22471
-
22472
22494
  // store the segmentation presentation id in the viewport info
22473
22495
  this.storePresentation({
22474
22496
  viewportId: viewport.id
22475
22497
  });
22498
+ return segmentationRepresentationPromise;
22499
+ }
22500
+ async _addOverlayRepresentations(overlayProcessingResults) {
22501
+ if (!overlayProcessingResults?.length) {
22502
+ return;
22503
+ }
22504
+ for (const overlayProcessingResult of overlayProcessingResults) {
22505
+ if (overlayProcessingResult?.addOverlayFn) {
22506
+ await overlayProcessingResult.addOverlayFn();
22507
+ }
22508
+ }
22476
22509
  }
22477
22510
 
22478
22511
  // Todo: keepCamera is an interim solution until we have a better solution for
@@ -22507,6 +22540,9 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22507
22540
  if ([esm.VolumeViewport, esm.VolumeViewport3D].some(type => viewport instanceof type)) {
22508
22541
  return this._setVolumeViewport(viewport, viewportData, viewportInfo, presentations);
22509
22542
  }
22543
+ if (viewport instanceof esm.ECGViewport) {
22544
+ return this._setEcgViewport(viewport, viewportData);
22545
+ }
22510
22546
  return this._setOtherViewport(viewport, viewportData, viewportInfo, presentations);
22511
22547
  }
22512
22548
 
@@ -22728,6 +22764,8 @@ CornerstoneViewportService.REGISTRATION = {
22728
22764
  }
22729
22765
  };
22730
22766
  /* harmony default export */ const ViewportService_CornerstoneViewportService = (CornerstoneViewportService);
22767
+ // EXTERNAL MODULE: ../../../extensions/cornerstone/src/utils/getDataIdForViewport.ts
22768
+ var getDataIdForViewport = __webpack_require__(67142);
22731
22769
  ;// ../../../extensions/cornerstone/src/types/Colorbar.ts
22732
22770
  // Position options
22733
22771
 
@@ -22770,6 +22808,7 @@ var _ColorbarService;
22770
22808
 
22771
22809
 
22772
22810
 
22811
+
22773
22812
  class ColorbarService extends src/* PubSubService */.Rc {
22774
22813
  constructor(servicesManager) {
22775
22814
  super(ColorbarService.EVENTS);
@@ -22793,23 +22832,6 @@ class ColorbarService extends src/* PubSubService */.Rc {
22793
22832
  this.servicesManager = servicesManager;
22794
22833
  }
22795
22834
 
22796
- /**
22797
- * Gets the appropriate data ID for a viewport and display set
22798
- * @param viewport - The viewport instance
22799
- * @param displaySetInstanceUID - The display set instance UID to identify data
22800
- * @returns The appropriate data ID for the viewport type (volumeId for volume viewports, undefined for stack)
22801
- */
22802
- getDataIdForViewport(viewport, displaySetInstanceUID) {
22803
- // For volume viewports, find the matching volumeId
22804
- if (viewport.getAllVolumeIds) {
22805
- const volumeIds = viewport.getAllVolumeIds() || [];
22806
- return volumeIds.length > 0 ? volumeIds.find(id => id.includes(displaySetInstanceUID)) || undefined : undefined;
22807
- }
22808
-
22809
- // For other viewports, no specific dataId is needed for now
22810
- return undefined;
22811
- }
22812
-
22813
22835
  /**
22814
22836
  * Adds a colorbar to a specific viewport identified by `viewportId`, using the provided `displaySetInstanceUIDs` and `options`.
22815
22837
  * This method prepares the colorbar state that will be used by the ViewportColorbarsContainer component.
@@ -22841,7 +22863,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
22841
22863
  if (displaySet.isOverlayDisplaySet) {
22842
22864
  return;
22843
22865
  }
22844
- const dataId = this.getDataIdForViewport(viewport, displaySetInstanceUID);
22866
+ const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
22845
22867
  const properties = dataId ? viewport.getProperties(dataId) : viewport.getProperties();
22846
22868
  const colormap = properties?.colormap;
22847
22869
  if (activeColormapName && !colormap) {
@@ -22979,7 +23001,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
22979
23001
  }
22980
23002
 
22981
23003
  // Get the appropriate dataId for this viewport/displaySet combination
22982
- const dataId = this.getDataIdForViewport(viewport, displaySetInstanceUID);
23004
+ const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
22983
23005
 
22984
23006
  // Set properties with or without dataId based on what the viewport supports
22985
23007
  viewport.setProperties({
@@ -23249,12 +23271,114 @@ const createFrameViewSynchronizer = synchronizerName => {
23249
23271
 
23250
23272
  // EXTERNAL MODULE: ../../../node_modules/dcmjs/build/dcmjs.es.js
23251
23273
  var dcmjs_es = __webpack_require__(5842);
23274
+ ;// ../../../extensions/cornerstone/src/utils/ecgMetadata.ts
23275
+ /**
23276
+ * Decode a multiplexed Int16 buffer into per-channel arrays.
23277
+ * Layout: sample0ch0, sample0ch1 ... sample0chN, sample1ch0, …
23278
+ * Note: DICOM ECG data is canonically SS (signed short). The sampleInterpretation
23279
+ * field is forwarded to ECGViewport for its own use; the raw buffer is always
23280
+ * treated as Int16 because Cornerstone ECGViewport expects Int16Array[].
23281
+ */
23282
+ function decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples) {
23283
+ const src = new Int16Array(buffer);
23284
+ const channels = [];
23285
+ for (let ch = 0; ch < numberOfChannels; ch++) {
23286
+ const out = new Int16Array(numberOfSamples);
23287
+ for (let s = 0; s < numberOfSamples; s++) {
23288
+ out[s] = src[s * numberOfChannels + ch];
23289
+ }
23290
+ channels.push(out);
23291
+ }
23292
+ return channels;
23293
+ }
23294
+
23295
+ /**
23296
+ * Decode a base64 InlineBinary string into a raw ArrayBuffer.
23297
+ */
23298
+ function base64ToArrayBuffer(base64) {
23299
+ const binaryStr = atob(base64);
23300
+ const bytes = new Uint8Array(binaryStr.length);
23301
+ for (let i = 0; i < binaryStr.length; i++) {
23302
+ bytes[i] = binaryStr.charCodeAt(i);
23303
+ }
23304
+ return bytes.buffer;
23305
+ }
23306
+ /**
23307
+ * Parse the naturalized DICOM instance's WaveformSequence and build the ecgModule
23308
+ * that Cornerstone's ECGViewport.setEcg() expects via
23309
+ * metaData.get(MetadataModules.ECG, imageId).
23310
+ *
23311
+ * Returns null if the instance has no WaveformSequence.
23312
+ */
23313
+ function buildEcgModule(instance, userAuthenticationService) {
23314
+ const waveformGroups = instance?.WaveformSequence;
23315
+ if (!waveformGroups?.length) {
23316
+ return null;
23317
+ }
23318
+
23319
+ // Use the first (and typically only) multiplex group
23320
+ const group = waveformGroups[0];
23321
+ const numberOfChannels = group.NumberOfWaveformChannels ?? 0;
23322
+ const numberOfSamples = group.NumberOfWaveformSamples ?? 0;
23323
+ const samplingFrequency = group.SamplingFrequency ?? 1;
23324
+ const bitsAllocated = group.WaveformBitsAllocated ?? 16;
23325
+ const sampleInterpretation = group.WaveformSampleInterpretation ?? 'SS';
23326
+ const multiplexGroupLabel = group.MultiplexGroupLabel ?? '';
23327
+ const channelDefinitionSequence = (group.ChannelDefinitionSequence ?? []).map(ch => ({
23328
+ channelSourceSequence: {
23329
+ codeMeaning: ch?.ChannelSourceSequence?.[0]?.CodeMeaning ?? ch?.ChannelSourceSequence?.[0]?.codeMeaning ?? ''
23330
+ }
23331
+ }));
23332
+ const retrieveBulkData = async () => {
23333
+ const waveformData = group.WaveformData;
23334
+ if (!waveformData) {
23335
+ console.warn('[ECGViewport] No WaveformData found on instance');
23336
+ return [];
23337
+ }
23338
+ let buffer;
23339
+ if (waveformData.InlineBinary) {
23340
+ buffer = base64ToArrayBuffer(waveformData.InlineBinary);
23341
+ } else if (waveformData.BulkDataURI) {
23342
+ const headers = {
23343
+ Accept: 'application/octet-stream'
23344
+ };
23345
+ const authHeader = userAuthenticationService?.getAuthorizationHeader?.();
23346
+ if (authHeader) {
23347
+ Object.assign(headers, authHeader);
23348
+ }
23349
+ const response = await fetch(waveformData.BulkDataURI, {
23350
+ headers
23351
+ });
23352
+ if (!response.ok) {
23353
+ throw new Error(`[ECGViewport] Failed to fetch waveform BulkDataURI: ${response.status}`);
23354
+ }
23355
+ buffer = await response.arrayBuffer();
23356
+ } else {
23357
+ console.warn('[ECGViewport] WaveformData has no InlineBinary or BulkDataURI');
23358
+ return [];
23359
+ }
23360
+ return decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples);
23361
+ };
23362
+ return {
23363
+ numberOfWaveformChannels: numberOfChannels,
23364
+ numberOfWaveformSamples: numberOfSamples,
23365
+ samplingFrequency,
23366
+ waveformBitsAllocated: bitsAllocated,
23367
+ waveformSampleInterpretation: sampleInterpretation,
23368
+ multiplexGroupLabel,
23369
+ channelDefinitionSequence,
23370
+ waveformData: {
23371
+ retrieveBulkData
23372
+ }
23373
+ };
23374
+ }
23252
23375
  ;// ../../../extensions/cornerstone/src/getSopClassHandlerModule.js
23253
23376
 
23254
23377
 
23255
23378
 
23256
23379
 
23257
23380
 
23381
+
23258
23382
  const {
23259
23383
  MetadataModules
23260
23384
  } = esm.Enums;
@@ -23265,9 +23389,9 @@ const {
23265
23389
  denaturalizeDataset
23266
23390
  } = dcmjs_es/* default.data */.Ay.data.DicomMetaDictionary;
23267
23391
  const {
23268
- transferDenaturalizedDataset,
23269
- fixMultiValueKeys
23270
- } = default_src.dicomWebUtils;
23392
+ /* transferDenaturalizedDataset */ "If": transferDenaturalizedDataset,
23393
+ /* fixMultiValueKeys */ "Uk": fixMultiValueKeys
23394
+ } = default_src/* dicomWebUtils */.CA;
23271
23395
  const SOP_CLASS_UIDS = {
23272
23396
  VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: '1.2.840.10008.5.1.4.1.1.77.1.6'
23273
23397
  };
@@ -23324,7 +23448,7 @@ function _getDisplaySetsFromSeries(instances, servicesManager, extensionManager)
23324
23448
  SOPInstanceUID,
23325
23449
  SeriesInstanceUID,
23326
23450
  StudyInstanceUID,
23327
- FrameOfReferenceUID,
23451
+ frameOfReferenceUID: FrameOfReferenceUID,
23328
23452
  SOPClassHandlerId,
23329
23453
  SOPClassUID,
23330
23454
  SeriesDescription: SeriesDescription || 'Microscopy Data',
@@ -23393,8 +23517,92 @@ function getDicomMicroscopySopClassHandler({
23393
23517
  getDisplaySetsFromSeries
23394
23518
  };
23395
23519
  }
23520
+
23521
+ /**
23522
+ * DICOM Waveform SOP Class UIDs for ECG / cardiac electrophysiology.
23523
+ * Reference: https://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.5.html
23524
+ */
23525
+ const ECG_SOP_CLASS_UIDS = {
23526
+ TWELVE_LEAD_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.1',
23527
+ GENERAL_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.2',
23528
+ AMBULATORY_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.3',
23529
+ HEMODYNAMIC_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.2.1',
23530
+ CARDIAC_ELECTROPHYSIOLOGY_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.3.1'
23531
+ };
23532
+ const ecgSopClassUids = Object.values(ECG_SOP_CLASS_UIDS);
23533
+ const DicomEcgSOPClassHandlerId = '@ohif/extension-cornerstone.sopClassHandlerModule.DicomEcgSopClassHandler';
23534
+ function _getEcgDisplaySetsFromSeries(instances, servicesManager) {
23535
+ const {
23536
+ userAuthenticationService
23537
+ } = servicesManager.services;
23538
+ return instances.map(instance => {
23539
+ const {
23540
+ Modality,
23541
+ SOPInstanceUID
23542
+ } = instance;
23543
+ const {
23544
+ SeriesDescription,
23545
+ SeriesNumber,
23546
+ SeriesDate
23547
+ } = instance;
23548
+ const {
23549
+ SeriesInstanceUID,
23550
+ StudyInstanceUID,
23551
+ SOPClassUID
23552
+ } = instance;
23553
+ const imageId = instance.imageId;
23554
+
23555
+ // Register ECG metadata in the OHIF metadata provider so that
23556
+ // Cornerstone's ECGViewport can retrieve it via metaData.get('ecgModule', imageId).
23557
+ if (imageId) {
23558
+ const ecgModule = buildEcgModule(instance, userAuthenticationService);
23559
+ if (ecgModule) {
23560
+ esm.utilities.genericMetadataProvider.addRaw(imageId, {
23561
+ type: MetadataModules.ECG,
23562
+ metadata: ecgModule
23563
+ });
23564
+ }
23565
+ }
23566
+ return {
23567
+ Modality,
23568
+ displaySetInstanceUID: getSopClassHandlerModule_utils.guid(),
23569
+ SeriesDescription,
23570
+ SeriesNumber,
23571
+ SeriesDate,
23572
+ SOPInstanceUID,
23573
+ SeriesInstanceUID,
23574
+ StudyInstanceUID,
23575
+ SOPClassHandlerId: DicomEcgSOPClassHandlerId,
23576
+ SOPClassUID,
23577
+ referencedImages: null,
23578
+ measurements: null,
23579
+ viewportType: esm.Enums.ViewportType.ECG,
23580
+ instances: [instance],
23581
+ instance,
23582
+ thumbnailSrc: null,
23583
+ isDerivedDisplaySet: false,
23584
+ isLoaded: false,
23585
+ sopClassUids: ecgSopClassUids,
23586
+ numImageFrames: 0,
23587
+ numInstances: 1,
23588
+ imageIds: imageId ? [imageId] : [],
23589
+ supportsWindowLevel: false,
23590
+ label: SeriesDescription || 'ECG'
23591
+ };
23592
+ });
23593
+ }
23594
+ function getDicomEcgSopClassHandler({
23595
+ servicesManager
23596
+ }) {
23597
+ const getDisplaySetsFromSeries = instances => _getEcgDisplaySetsFromSeries(instances, servicesManager);
23598
+ return {
23599
+ name: 'DicomEcgSopClassHandler',
23600
+ sopClassUids: ecgSopClassUids,
23601
+ getDisplaySetsFromSeries
23602
+ };
23603
+ }
23396
23604
  function getSopClassHandlerModule(params) {
23397
- return [getDicomMicroscopySopClassHandler(params)];
23605
+ return [getDicomMicroscopySopClassHandler(params), getDicomEcgSopClassHandler(params)];
23398
23606
  }
23399
23607
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/hooks/useActiveViewportSegmentationRepresentations.ts
23400
23608
  var useActiveViewportSegmentationRepresentations = __webpack_require__(9234);
@@ -23424,7 +23632,7 @@ function SegmentationUtilityButton(props) {
23424
23632
  isActive,
23425
23633
  id
23426
23634
  } = props;
23427
- const activeSegmentationUtility = (0,default_src.useUIStateStore)(store => store.uiState.activeSegmentationUtility);
23635
+ const activeSegmentationUtility = (0,default_src/* useUIStateStore */.FS)(store => store.uiState.activeSegmentationUtility);
23428
23636
  const toolButtonClassName = (0,ui_next_src.cn)('w-7 h-7 text-primary hover:text-primary hover:!bg-primary/30', className, isActive && 'bg-primary/30');
23429
23637
  const handleMouseDownCapture = (0,react.useCallback)(event => {
23430
23638
  if (activeSegmentationUtility === id) {
@@ -23555,7 +23763,7 @@ function PanelSegmentation({
23555
23763
  segmentationsWithRepresentations,
23556
23764
  disabled
23557
23765
  } = (0,useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c)();
23558
- const setUIState = (0,default_src.useUIStateStore)(store => store.setUIState);
23766
+ const setUIState = (0,default_src/* useUIStateStore */.FS)(store => store.setUIState);
23559
23767
 
23560
23768
  // useEffect for handling clicks on any of the non-active viewports.
23561
23769
  // The ViewportGrid stops the propagation of pointer/mouse events
@@ -23816,7 +24024,7 @@ function PanelSegmentation({
23816
24024
  IconContainer: components_SegmentationUtilityButton
23817
24025
  }, /*#__PURE__*/react.createElement("div", {
23818
24026
  className: "flex flex-wrap gap-[3px] bg-transparent pb-[2px] pl-[8px] pt-[6px]"
23819
- }, /*#__PURE__*/react.createElement(default_src.Toolbar, {
24027
+ }, /*#__PURE__*/react.createElement(default_src/* Toolbar */.M7, {
23820
24028
  buttonSection: buttonSection
23821
24029
  })));
23822
24030
  };
@@ -24343,12 +24551,12 @@ function DefaultAccordion(props) {
24343
24551
  if (!allChildren || !groups) {
24344
24552
  return null;
24345
24553
  }
24346
- if (Boolean(asChild)) {
24554
+ if (asChild) {
24347
24555
  return /*#__PURE__*/react.cloneElement(props.children, props);
24348
24556
  }
24349
24557
  return /*#__PURE__*/react.createElement(ui_next_src/* Accordion */.nD3, {
24350
24558
  type: grouping.type || 'multiple',
24351
- className: "text-white",
24559
+ className: "text-foreground",
24352
24560
  defaultValue: defaultValue
24353
24561
  }, [...groups.entries()].map(([key, group]) => {
24354
24562
  return /*#__PURE__*/react.createElement(ui_next_src/* AccordionItem */.AsP, {
@@ -24826,7 +25034,7 @@ function PanelMeasurement(props) {
24826
25034
  return EmptyComponent ? /*#__PURE__*/react.createElement(EmptyComponent, {
24827
25035
  items: displayMeasurements
24828
25036
  }) : /*#__PURE__*/react.createElement("span", {
24829
- className: "text-white"
25037
+ className: "text-foreground"
24830
25038
  }, "No Measurements");
24831
25039
  }
24832
25040
  if (children) {
@@ -24891,7 +25099,7 @@ const getPanelModule = ({
24891
25099
  } = (0,es/* useTranslation */.Bd)('SegmentationPanel');
24892
25100
  const tKey = `${props.segmentationRepresentationTypes?.[0] ?? 'Segmentation'} tools`;
24893
25101
  const tValue = t(tKey);
24894
- return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src.Toolbox, {
25102
+ return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src/* Toolbox */.OO, {
24895
25103
  buttonSectionId: toolSectionMap[props.segmentationRepresentationTypes?.[0]],
24896
25104
  title: tValue
24897
25105
  }), /*#__PURE__*/react.createElement(PanelSegmentation, {
@@ -25245,7 +25453,7 @@ function promptHydrationDialog({
25245
25453
  customizationService
25246
25454
  } = servicesManager.services;
25247
25455
  const extensionManager = servicesManager._extensionManager;
25248
- const appConfig = extensionManager._appConfig;
25456
+ const appConfig = extensionManager.appConfig;
25249
25457
 
25250
25458
  // Todo: make this use enum from the extension, we should move the enum
25251
25459
  const standardMode = appConfig?.measurementTrackingMode === 'standard';
@@ -25262,20 +25470,30 @@ function promptHydrationDialog({
25262
25470
  if (type === HydrationType.SEG) {
25263
25471
  // SEG needs setTimeout
25264
25472
  window.setTimeout(async () => {
25265
- const isHydrated = await hydrateCallback({
25266
- segDisplaySet: displaySet,
25267
- viewportId
25268
- });
25269
- resolve(isHydrated);
25473
+ try {
25474
+ const isHydrated = await hydrateCallback({
25475
+ segDisplaySet: displaySet,
25476
+ viewportId
25477
+ });
25478
+ resolve(isHydrated);
25479
+ } catch (error) {
25480
+ reject(error);
25481
+ }
25270
25482
  }, 0);
25271
25483
  } else if (type === HydrationType.RTSTRUCT) {
25272
25484
  // RT hydration
25273
- const isHydrated = await hydrateCallback({
25274
- rtDisplaySet: displaySet,
25275
- viewportId,
25276
- servicesManager
25277
- });
25278
- resolve(isHydrated);
25485
+ window.setTimeout(async () => {
25486
+ try {
25487
+ const isHydrated = await hydrateCallback({
25488
+ rtDisplaySet: displaySet,
25489
+ viewportId,
25490
+ servicesManager
25491
+ });
25492
+ resolve(isHydrated);
25493
+ } catch (error) {
25494
+ reject(error);
25495
+ }
25496
+ }, 0);
25279
25497
  } else if (type === HydrationType.SR) {
25280
25498
  // SR has a different result structure
25281
25499
  const hydrationResult = await hydrateCallback(displaySet);
@@ -25368,7 +25586,8 @@ const setUpSegmentationEventHandlers = ({
25368
25586
  const {
25369
25587
  segmentationService,
25370
25588
  customizationService,
25371
- displaySetService
25589
+ displaySetService,
25590
+ viewportGridService
25372
25591
  } = servicesManager.services;
25373
25592
  const {
25374
25593
  unsubscribe: unsubscribeSegmentationDataModifiedHandler
@@ -25413,12 +25632,42 @@ const setUpSegmentationEventHandlers = ({
25413
25632
  };
25414
25633
  displaySetService.addDisplaySets(segmentationDisplaySet);
25415
25634
  });
25635
+ const {
25636
+ unsubscribe: unsubscribeSegmentationRemoved
25637
+ } = segmentationService.subscribe(segmentationService.EVENTS.SEGMENTATION_REMOVED, ({
25638
+ segmentationId
25639
+ }) => {
25640
+ const displaySet = displaySetService.getDisplaySetByUID(segmentationId);
25641
+
25642
+ // Remove the display set layer from all viewports that have it
25643
+ if (displaySet) {
25644
+ const state = viewportGridService.getState();
25645
+ const viewports = state.viewports;
25646
+
25647
+ // Find all viewports that contain this segmentation's display set as a layer
25648
+ for (const [viewportId, viewport] of viewports.entries()) {
25649
+ const displaySetInstanceUIDs = viewport.displaySetInstanceUIDs || [];
25650
+ if (displaySetInstanceUIDs.includes(segmentationId)) {
25651
+ // Remove the display set layer from this viewport
25652
+ commandsManager.runCommand('removeDisplaySetLayer', {
25653
+ viewportId,
25654
+ displaySetInstanceUID: segmentationId
25655
+ });
25656
+ }
25657
+ }
25658
+
25659
+ // Delete the display set from the service if it was made in client
25660
+ if (displaySet.madeInClient) {
25661
+ displaySetService.deleteDisplaySet(segmentationId);
25662
+ }
25663
+ }
25664
+ });
25416
25665
  const {
25417
25666
  unsubscribeSelectedSegmentationsForViewportEvents
25418
25667
  } = setUpSelectedSegmentationsForViewportHandler({
25419
25668
  segmentationService
25420
25669
  });
25421
- const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, ...unsubscribeSelectedSegmentationsForViewportEvents];
25670
+ const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, unsubscribeSegmentationRemoved, ...unsubscribeSelectedSegmentationsForViewportEvents];
25422
25671
  return {
25423
25672
  unsubscriptions
25424
25673
  };
@@ -25561,7 +25810,7 @@ function PanelAccordionTrigger(props) {
25561
25810
  }, /*#__PURE__*/react.createElement("button", {
25562
25811
  onClick: onClickDefault.bind(props)
25563
25812
  }, /*#__PURE__*/react.createElement("span", {
25564
- className: `inline-flex rounded-l border-r border-black ${isActive ? 'bg-highlight' : 'bg-muted'}`
25813
+ className: `inline-flex rounded-l border-r border-background ${isActive ? 'bg-highlight' : 'bg-muted'}`
25565
25814
  }, count !== undefined ? /*#__PURE__*/react.createElement("span", {
25566
25815
  className: "px-2"
25567
25816
  }, count) : null, colorHex && /*#__PURE__*/react.createElement(ui_next_src/* ColorCircle */.cd8, {
@@ -25909,7 +26158,7 @@ const cornerstoneExtension = {
25909
26158
  useLutPresentationStore/* useLutPresentationStore */.I.getState().clearLutPresentationStore();
25910
26159
  usePositionPresentationStore/* usePositionPresentationStore */.q.getState().clearPositionPresentationStore();
25911
26160
  useSynchronizersStore/* useSynchronizersStore */.U.getState().clearSynchronizersStore();
25912
- default_src.useToggleOneUpViewportGridStore.getState().clearToggleOneUpViewportGridStore();
26161
+ default_src/* useToggleOneUpViewportGridStore */.Yd.getState().clearToggleOneUpViewportGridStore();
25913
26162
  useSegmentationPresentationStore/* useSegmentationPresentationStore */.v.getState().clearSegmentationPresentationStore();
25914
26163
  useSelectedSegmentationsForViewportStore.getState().clearSelectedSegmentationsForViewportStore();
25915
26164
  segmentationService.removeAllSegmentations();
@@ -26000,10 +26249,10 @@ const cornerstoneExtension = {
26000
26249
 
26001
26250
  /* harmony default export */ const cornerstone_src = (cornerstoneExtension);
26002
26251
 
26003
- /***/ }),
26252
+ /***/ },
26004
26253
 
26005
- /***/ 71353:
26006
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26254
+ /***/ 71353
26255
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26007
26256
 
26008
26257
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26009
26258
  /* harmony export */ cL: () => (/* binding */ reset),
@@ -26042,10 +26291,10 @@ const reset = () => {
26042
26291
  };
26043
26292
 
26044
26293
 
26045
- /***/ }),
26294
+ /***/ },
26046
26295
 
26047
- /***/ 46026:
26048
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26296
+ /***/ 46026
26297
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26049
26298
 
26050
26299
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26051
26300
  /* harmony export */ FG: () => (/* binding */ JOIN_STR),
@@ -26085,10 +26334,10 @@ const addUniqueIndex = (arr, key, viewports, isUpdatingSameViewport) => {
26085
26334
  };
26086
26335
 
26087
26336
 
26088
- /***/ }),
26337
+ /***/ },
26089
26338
 
26090
- /***/ 10182:
26091
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26339
+ /***/ 10182
26340
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26092
26341
 
26093
26342
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26094
26343
  /* harmony export */ I: () => (/* binding */ useLutPresentationStore)
@@ -26200,10 +26449,10 @@ const useLutPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .creat
26200
26449
  name: 'LutPresentationStore'
26201
26450
  }) : createLutPresentationStore);
26202
26451
 
26203
- /***/ }),
26452
+ /***/ },
26204
26453
 
26205
- /***/ 44646:
26206
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26454
+ /***/ 44646
26455
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26207
26456
 
26208
26457
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26209
26458
  /* harmony export */ q: () => (/* binding */ usePositionPresentationStore)
@@ -26311,10 +26560,10 @@ const usePositionPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .
26311
26560
  name: 'PositionPresentationStore'
26312
26561
  }) : createPositionPresentationStore);
26313
26562
 
26314
- /***/ }),
26563
+ /***/ },
26315
26564
 
26316
- /***/ 2847:
26317
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26565
+ /***/ 2847
26566
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26318
26567
 
26319
26568
 
26320
26569
  // EXPORTS
@@ -26520,10 +26769,10 @@ const useSegmentationPresentationStore = (0,esm/* create */.vt)()(DEBUG_STORE ?
26520
26769
  name: 'Segmentation Presentation Store'
26521
26770
  }) : createSegmentationPresentationStore);
26522
26771
 
26523
- /***/ }),
26772
+ /***/ },
26524
26773
 
26525
- /***/ 68578:
26526
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26774
+ /***/ 68578
26775
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26527
26776
 
26528
26777
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26529
26778
  /* harmony export */ U: () => (/* binding */ useSynchronizersStore)
@@ -26584,6 +26833,32 @@ const useSynchronizersStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .create
26584
26833
  name: 'SynchronizersStore'
26585
26834
  }) : createSynchronizersStore);
26586
26835
 
26587
- /***/ })
26836
+ /***/ },
26837
+
26838
+ /***/ 67142
26839
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26840
+
26841
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26842
+ /* harmony export */ V: () => (/* binding */ getDataIdForViewport)
26843
+ /* harmony export */ });
26844
+ /**
26845
+ * Resolves the data ID (e.g. volumeId) for a viewport and display set.
26846
+ * For viewports with multiple volumes/actors, returns the id that matches the display set; otherwise undefined.
26847
+ * Use this to call viewport.getProperties(dataId) in a viewport-type-agnostic way.
26848
+ *
26849
+ * @param viewport - Viewport instance (stack, volume, or future types with optional getAllVolumeIds)
26850
+ * @param displaySetInstanceUID - Display set instance UID to match
26851
+ * @returns volumeId (or equivalent) for multi-actor viewports, undefined for single-actor
26852
+ */
26853
+ function getDataIdForViewport(viewport, displaySetInstanceUID) {
26854
+ const vp = viewport;
26855
+ if (typeof vp.getAllVolumeIds !== 'function') {
26856
+ return undefined;
26857
+ }
26858
+ const volumeIds = vp.getAllVolumeIds() || [];
26859
+ return volumeIds.length > 0 ? volumeIds.find(id => id.includes(displaySetInstanceUID)) ?? undefined : undefined;
26860
+ }
26861
+
26862
+ /***/ }
26588
26863
 
26589
26864
  }]);