@ohif/app 3.13.0-beta.6 → 3.13.0-beta.60

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 (71) hide show
  1. package/dist/{1459.bundle.075e535250e3d4779923.js → 1459.bundle.ed7323f44e4ff4ecd69a.js} +5 -6
  2. package/dist/{147.bundle.37d627289453cb6c3937.js → 147.bundle.173b4a11960d03a3b5b0.js} +21 -45
  3. package/dist/{1608.bundle.0687c661f1c9edfb3b8a.js → 1608.bundle.e4aadbf17d38143dacdf.js} +12 -12
  4. package/dist/{1927.bundle.3050588e95f43cf57cdd.js → 1927.bundle.be67b3aafe238ca9f191.js} +27 -38
  5. package/dist/{1933.bundle.317997210b6a51079753.js → 1933.bundle.0055c536e1392867e57c.js} +32 -27
  6. package/dist/{2018.bundle.31d14d6f9fb764b51bda.js → 2018.bundle.ab8f9ceeae0e18eb303b.js} +18 -19
  7. package/dist/{6409.bundle.b36048896cb11c8571fb.js → 2075.bundle.23265b8e7597c398db4f.js} +327 -256
  8. package/dist/{2108.bundle.e84aa8d858d8c4f2413e.js → 2108.bundle.aea8d3b39486dd5ab39e.js} +569 -558
  9. package/dist/{213.bundle.363f9a3eb6c0d33e3921.js → 213.bundle.18a8b5a1e2f00de7feaf.js} +3 -5
  10. package/dist/{2424.bundle.aa7f4df6cba71b817c87.js → 2424.bundle.5e858661a06aa36dd859.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.b591cf6385ed53ed6093.js} +10 -10
  13. package/dist/{9195.bundle.adf6a548b6f7ae279c09.js → 2851.bundle.c5202066974b96955c28.js} +384 -169
  14. package/dist/{1730.bundle.1d137db2556d538263fb.js → 3138.bundle.5ed994e6e0ff7c720a75.js} +16 -310
  15. package/dist/{3461.bundle.7024d5e66d12b4069031.js → 3461.bundle.54f8d64ed1965c14ec4c.js} +131 -107
  16. package/dist/{4202.bundle.5a0f8e4004c5d8a68548.js → 4202.bundle.850a7c7c011800b3daea.js} +6 -6
  17. package/dist/{4019.bundle.83a604779f7da0101ced.js → 4287.bundle.b7840e7b94cbbc102236.js} +348 -237
  18. package/dist/{5462.bundle.21beddaca145b7465c72.js → 4406.bundle.573d234b4641d23cf8db.js} +1083 -1308
  19. package/dist/{1403.bundle.40baf30d503370ce52c9.js → 4507.bundle.18379f328211aee3aba5.js} +10 -305
  20. package/dist/{6347.bundle.784c48912700f281de1d.js → 4579.bundle.0a6b2f49a7e136a79e37.js} +561 -649
  21. package/dist/{3081.bundle.f0df1c7d93ef4be29102.js → 4688.bundle.e23f20a556dca69540fd.js} +742 -408
  22. package/dist/{4819.bundle.0c37918802ef7805586f.js → 4819.bundle.fb82fcc8360f4883691e.js} +39 -39
  23. package/dist/{4775.bundle.5d6203a2991902544266.js → 5015.bundle.dda760490cf19777b6b3.js} +29 -333
  24. package/dist/{5028.bundle.2cd4d2253b47845e6634.js → 5028.bundle.494b6ca9e0f5567c26e2.js} +11 -13
  25. package/dist/{5261.bundle.6e1a017f8f1027557f5b.js → 5261.bundle.2655560097e9250eac44.js} +412 -345
  26. package/dist/{5457.bundle.15d4adb3ca43c45b044d.js → 5457.bundle.328f29b05df8d287491b.js} +16 -23
  27. package/dist/{5485.bundle.b9764a7846d57ee5710d.js → 5485.bundle.53614f38e6ee0e052bdc.js} +20 -32
  28. package/dist/{5491.bundle.2e01dd7ad29e4cc01bc1.js → 5491.bundle.4866d2ecb20dd089e071.js} +54 -51
  29. package/dist/{5802.bundle.3bf5e6b3ab330a594a47.js → 5802.bundle.41cf74cda9aad21601e8.js} +79 -20
  30. package/dist/5802.css +1 -1
  31. package/dist/{5830.bundle.b073c265c4fcea1afff3.js → 5830.bundle.791019deddd536980a11.js} +3 -3
  32. package/dist/{5858.bundle.ff6b340cf7457db76a1a.js → 5858.bundle.466e58128de344ab53f3.js} +90 -86
  33. package/dist/{6027.bundle.55f4bf16015381255f33.js → 6027.bundle.1bfe806a0cb494dfc265.js} +3 -5
  34. package/dist/{6354.bundle.c387737dc09c9cab4ff2.js → 6354.bundle.929febcf6d326e582e00.js} +151 -140
  35. package/dist/{6376.bundle.9cb74d7bc08476e2f1a7.js → 6376.bundle.738c873196491232acb6.js} +6 -6
  36. package/dist/{2842.bundle.860b9f10fcdd9656947a.js → 6386.bundle.5d82d1f41d1c37a0358d.js} +904 -2298
  37. package/dist/6939.bundle.41fbdef87597b5172ec6.js +3 -3
  38. package/dist/{7159.bundle.a5991a5d4f0dd8f1c95f.js → 7159.bundle.fb9df255868960f69765.js} +7 -5
  39. package/dist/{7190.bundle.e8f0193e0e06472f795c.js → 7190.bundle.3738008038e70525764f.js} +1129 -821
  40. package/dist/{732.bundle.6978ac30a1e36abf06db.js → 732.bundle.ea6f9d8504e37e01a208.js} +5 -13
  41. package/dist/{7431.bundle.b01791d10e6cf9f503b0.js → 7431.bundle.5e14641f2c71e852abe7.js} +28 -28
  42. package/dist/{4410.bundle.c5224cd7d6238a7d4660.js → 7537.bundle.1726a7f7a4c378296085.js} +5216 -2238
  43. package/dist/{7639.bundle.9057c381d5f455997d60.js → 7639.bundle.2ec2272d8eb08df56b66.js} +3 -5
  44. package/dist/7758.bundle.c8d106364298e7d288f0.js +3 -3
  45. package/dist/{8094.bundle.5c44190a325ac23e3e5c.js → 8094.bundle.148a66619607e37cbf19.js} +3 -4
  46. package/dist/{8305.bundle.2a215d860aa3bb1984f6.js → 8305.bundle.21d4c7deff19f6ce9a6a.js} +71 -66
  47. package/dist/{6163.bundle.18484c031c76e3835a71.js → 8499.bundle.dbeca38ee1d1471ce4d8.js} +7 -302
  48. package/dist/8499.css +2 -0
  49. package/dist/{85.bundle.173a5ab4b47890e2f013.js → 85.bundle.e426258a9ad5bcf9bb3e.js} +3 -5
  50. package/dist/{8558.bundle.52d7001a86845c8a91b8.js → 8558.bundle.5c64a061bf4d5d5f6d7a.js} +15 -309
  51. package/dist/{8583.bundle.e899badfa6f91f22b2f3.js → 8583.bundle.a0ccedd0799600ad5fad.js} +24 -27
  52. package/dist/{997.bundle.822b33e561263084e18c.js → 9039.bundle.7afa93b103c3b26d4855.js} +3965 -2984
  53. package/dist/{7412.bundle.fab1742191b7fe937330.js → 9205.bundle.315c3b56464a7590235a.js} +6071 -3305
  54. package/dist/{3584.bundle.8cc0750425513433e9cc.js → 9567.bundle.be350438bed4e656f278.js} +3422 -2880
  55. package/dist/{9845.bundle.255e7c7f7a88193b4e47.js → 9845.bundle.267831496ba080d9f8da.js} +10 -10
  56. package/dist/{9862.bundle.3a8958a82c572015d25d.js → 9862.bundle.09783830f0cb75a84d2a.js} +8 -6
  57. package/dist/{9927.bundle.0e4c7a7682b7acad3060.js → 9927.bundle.3bdd61e78a710e09cc0b.js} +4 -6
  58. package/dist/app-config.js +12 -0
  59. package/dist/{app.bundle.62d84a3df6ec149a44a6.js → app.bundle.348a74b1a7aeb7c8d0a8.js} +100482 -97633
  60. package/dist/app.bundle.css +3 -3
  61. package/dist/{polySeg.bundle.a5aa9130b4191253c410.js → compute.bundle.a41ec0ba4f935200ab93.js} +8 -20
  62. package/dist/{histogram-worker.bundle.d4e40a8018d2698b072e.js → histogram-worker.bundle.a2a50c4674d99c619ca7.js} +11 -23
  63. package/dist/index.html +1 -1
  64. package/dist/{interpolation.bundle.c70cb95d164dc494e6dc.js → interpolation.bundle.2559b710030605fc2bc6.js} +14 -26
  65. package/dist/{compute.bundle.64280c7af19ff567465f.js → polySeg.bundle.be57af5b834dd833a418.js} +10 -22
  66. package/dist/sw.js +1 -1
  67. package/package.json +23 -22
  68. package/dist/3343.bundle.d7578ce8f75d158c0bab.js +0 -297
  69. /package/dist/{1730.css → 3138.css} +0 -0
  70. /package/dist/{3343.css → 4972.css} +0 -0
  71. /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 + 3084 modules
29
+ var src = __webpack_require__(15953);
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__(15953);
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 + 3084 modules
502
+ var ui_next_src = __webpack_require__(15953);
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
@@ -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;
1018
1006
  }
1007
+ if (properties.voiRange) {
1008
+ setVoiRange(properties.voiRange);
1009
+ voiRangeRef.current = properties.voiRange;
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
 
@@ -1810,8 +1748,8 @@ function destroy() {
1810
1748
  var ai_dist_esm = __webpack_require__(75165);
1811
1749
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/polymorphic-segmentation/dist/esm/index.js + 14 modules
1812
1750
  var polymorphic_segmentation_dist_esm = __webpack_require__(56983);
1813
- // EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 139 modules
1814
- var default_src = __webpack_require__(39195);
1751
+ // EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 140 modules
1752
+ var default_src = __webpack_require__(62851);
1815
1753
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/state.ts
1816
1754
  var state = __webpack_require__(71353);
1817
1755
  ;// ../../../extensions/cornerstone/src/utils/getViewportEnabledElement.ts
@@ -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 + 3084 modules
7428
+ var ui_next_src = __webpack_require__(15953);
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
@@ -10799,7 +10792,7 @@ function commandsModule({
10799
10792
  // get the active segmentIndex bidirectional annotation and jump to it
10800
10793
  const activeBidirectional = bidirectionalData.find(measurement => measurement.segmentIndex === targetIndex);
10801
10794
  commandsManager.run('jumpToMeasurement', {
10802
- uid: activeBidirectional.annotationUID
10795
+ uid: activeBidirectional?.annotationUID
10803
10796
  });
10804
10797
  },
10805
10798
  interpolateLabelmap: () => {
@@ -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,
@@ -11099,6 +11092,9 @@ function commandsModule({
11099
11092
  uid,
11100
11093
  displayMeasurements = []
11101
11094
  }) => {
11095
+ if (!uid) {
11096
+ return;
11097
+ }
11102
11098
  measurementService.jumpToMeasurement(viewportGridService.getActiveViewportId(), uid);
11103
11099
  for (const measurement of displayMeasurements) {
11104
11100
  measurement.isActive = measurement.uid === uid;
@@ -11196,7 +11192,7 @@ function commandsModule({
11196
11192
  const labelConfig = customizationService.getCustomization('measurementLabels');
11197
11193
  const renderContent = customizationService.getCustomization('ui.labellingComponent');
11198
11194
  if (!labelConfig) {
11199
- const label = await (0,default_src.callInputDialog)({
11195
+ const label = await (0,default_src/* callInputDialog */.l5)({
11200
11196
  uiDialogService,
11201
11197
  title: i18n_src/* default */.A.t('Tools:Edit Arrow Text'),
11202
11198
  placeholder: data?.data?.label || i18n_src/* default */.A.t('Tools:Enter new text'),
@@ -11205,7 +11201,7 @@ function commandsModule({
11205
11201
  callback?.(label);
11206
11202
  return;
11207
11203
  }
11208
- const value = await (0,default_src.callInputDialogAutoComplete)({
11204
+ const value = await (0,default_src/* callInputDialogAutoComplete */.fq)({
11209
11205
  uiDialogService,
11210
11206
  labelConfig,
11211
11207
  renderContent
@@ -12101,7 +12097,7 @@ function commandsModule({
12101
12097
  segmentationService,
12102
12098
  viewportGridService
12103
12099
  } = servicesManager.services;
12104
- const displaySetInstanceUIDs = await (0,default_src.createReportAsync)({
12100
+ const displaySetInstanceUIDs = await (0,default_src/* createReportAsync */.Vy)({
12105
12101
  servicesManager,
12106
12102
  getReport: () => commandsManager.runCommand('storeSegmentation', args),
12107
12103
  reportType: 'Segmentation'
@@ -12178,14 +12174,15 @@ function commandsModule({
12178
12174
  * @param props.segmentationId - The ID of the segmentation to remove
12179
12175
  */
12180
12176
  removeSegmentationFromViewportCommand: ({
12181
- segmentationId
12177
+ segmentationId: displaySetInstanceUID
12182
12178
  }) => {
12183
12179
  const {
12184
- segmentationService,
12185
12180
  viewportGridService
12186
12181
  } = servicesManager.services;
12187
- segmentationService.removeSegmentationRepresentations(viewportGridService.getActiveViewportId(), {
12188
- segmentationId
12182
+ const viewportId = viewportGridService.getActiveViewportId();
12183
+ commandsManager.runCommand('removeDisplaySetLayer', {
12184
+ viewportId,
12185
+ displaySetInstanceUID
12189
12186
  });
12190
12187
  },
12191
12188
  /**
@@ -12213,7 +12210,7 @@ function commandsModule({
12213
12210
  return;
12214
12211
  }
12215
12212
  const segment = segmentation.segments[segmentIndex];
12216
- (0,default_src.callInputDialog)({
12213
+ (0,default_src/* callInputDialog */.l5)({
12217
12214
  uiDialogService,
12218
12215
  title: i18n_src/* default */.A.t('Tools:Edit Segment Label'),
12219
12216
  placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
@@ -12236,7 +12233,7 @@ function commandsModule({
12236
12233
  const {
12237
12234
  label
12238
12235
  } = segmentation;
12239
- (0,default_src.callInputDialog)({
12236
+ (0,default_src/* callInputDialog */.l5)({
12240
12237
  uiDialogService,
12241
12238
  title: i18n_src/* default */.A.t('Tools:Edit Segmentation Label'),
12242
12239
  placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
@@ -12266,7 +12263,7 @@ function commandsModule({
12266
12263
  a: color[3] / 255.0
12267
12264
  };
12268
12265
  uiDialogService.show({
12269
- content: default_src.colorPickerDialog,
12266
+ content: default_src/* colorPickerDialog */.wS,
12270
12267
  title: i18n_src/* default */.A.t('Tools:Segment Color'),
12271
12268
  contentProps: {
12272
12269
  value: rgbaColor,
@@ -13256,6 +13253,29 @@ const HYDRATE_SEG_SYNC_GROUP = {
13256
13253
  matchingRules: ['sameFOR']
13257
13254
  }
13258
13255
  };
13256
+ const viewportStructure = {
13257
+ layoutType: 'grid',
13258
+ properties: {
13259
+ rows: 1,
13260
+ columns: 3,
13261
+ layoutOptions: [{
13262
+ x: 0,
13263
+ y: 0,
13264
+ width: 1 / 3,
13265
+ height: 1
13266
+ }, {
13267
+ x: 1 / 3,
13268
+ y: 0,
13269
+ width: 1 / 3,
13270
+ height: 1
13271
+ }, {
13272
+ x: 2 / 3,
13273
+ y: 0,
13274
+ width: 1 / 3,
13275
+ height: 1
13276
+ }]
13277
+ }
13278
+ };
13259
13279
  const mpr = {
13260
13280
  id: 'mpr',
13261
13281
  name: i18next/* default */.A.t('Hps:MPR'),
@@ -13286,29 +13306,7 @@ const mpr = {
13286
13306
  },
13287
13307
  stages: [{
13288
13308
  name: 'MPR 1x3',
13289
- viewportStructure: {
13290
- layoutType: 'grid',
13291
- properties: {
13292
- rows: 1,
13293
- columns: 3,
13294
- layoutOptions: [{
13295
- x: 0,
13296
- y: 0,
13297
- width: 1 / 3,
13298
- height: 1
13299
- }, {
13300
- x: 1 / 3,
13301
- y: 0,
13302
- width: 1 / 3,
13303
- height: 1
13304
- }, {
13305
- x: 2 / 3,
13306
- y: 0,
13307
- width: 1 / 3,
13308
- height: 1
13309
- }]
13310
- }
13311
- },
13309
+ viewportStructure,
13312
13310
  viewports: [{
13313
13311
  viewportOptions: {
13314
13312
  viewportId: 'mpr-axial',
@@ -13352,6 +13350,52 @@ const mpr = {
13352
13350
  id: 'activeDisplaySet'
13353
13351
  }]
13354
13352
  }]
13353
+ }, {
13354
+ name: 'MPR Reformat 1x3',
13355
+ viewportStructure,
13356
+ viewports: [{
13357
+ viewportOptions: {
13358
+ viewportId: 'mpr-axial',
13359
+ toolGroupId: 'mpr',
13360
+ viewportType: 'volume',
13361
+ orientation: 'axial_reformat',
13362
+ initialImageOptions: {
13363
+ preset: 'middle'
13364
+ },
13365
+ syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
13366
+ },
13367
+ displaySets: [{
13368
+ id: 'activeDisplaySet'
13369
+ }]
13370
+ }, {
13371
+ viewportOptions: {
13372
+ viewportId: 'mpr-sagittal',
13373
+ toolGroupId: 'mpr',
13374
+ viewportType: 'volume',
13375
+ orientation: 'sagittal_reformat',
13376
+ initialImageOptions: {
13377
+ preset: 'middle'
13378
+ },
13379
+ syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
13380
+ },
13381
+ displaySets: [{
13382
+ id: 'activeDisplaySet'
13383
+ }]
13384
+ }, {
13385
+ viewportOptions: {
13386
+ viewportId: 'mpr-coronal',
13387
+ toolGroupId: 'mpr',
13388
+ viewportType: 'volume',
13389
+ orientation: 'coronal_reformat',
13390
+ initialImageOptions: {
13391
+ preset: 'middle'
13392
+ },
13393
+ syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
13394
+ },
13395
+ displaySets: [{
13396
+ id: 'activeDisplaySet'
13397
+ }]
13398
+ }]
13355
13399
  }]
13356
13400
  };
13357
13401
  ;// ../../../extensions/cornerstone/src/hps/fourUp.ts
@@ -15342,6 +15386,9 @@ function ViewportDataOverlayMenu({
15342
15386
  } = (0,useViewportDisplaySets/* useViewportDisplaySets */.N)(viewportId);
15343
15387
  const [optimisticOverlayDisplaySets, setOptimisticOverlayDisplaySets] = (0,react.useState)(overlayDisplaySets);
15344
15388
  const [thresholdOpacityEnabled, setThresholdOpacityEnabled] = (0,react.useState)(false);
15389
+ (0,react.useEffect)(() => {
15390
+ setOptimisticOverlayDisplaySets(overlayDisplaySets);
15391
+ }, [backgroundDisplaySet?.displaySetInstanceUID, overlayDisplaySets]);
15345
15392
 
15346
15393
  /**
15347
15394
  * Change the background display set
@@ -15648,7 +15695,8 @@ function ViewportDataOverlayMenu({
15648
15695
  }
15649
15696
  }
15650
15697
  }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
15651
- className: "flex-1"
15698
+ className: "flex-1",
15699
+ "data-cy": `overlay-background-ds-select-${viewportId}`
15652
15700
  }, /*#__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
15701
  key: displaySet.displaySetInstanceUID,
15654
15702
  value: displaySet.displaySetInstanceUID,
@@ -15923,7 +15971,7 @@ function ViewportOrientationMenu({
15923
15971
  }) : null), /*#__PURE__*/react.createElement("div", {
15924
15972
  className: "flex-1 text-left"
15925
15973
  }, "Acquisition")), /*#__PURE__*/react.createElement("div", {
15926
- className: "mx-1 my-2 border-t border-white/20"
15974
+ className: "border-input mx-1 my-2 border-t"
15927
15975
  }), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
15928
15976
  variant: "ghost",
15929
15977
  className: "flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0",
@@ -16264,7 +16312,7 @@ function VolumeRenderingPresetsContent({
16264
16312
  }
16265
16313
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.ByName, {
16266
16314
  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'
16315
+ 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
16316
  }), /*#__PURE__*/react.createElement("label", {
16269
16317
  className: "text-muted-foreground mt-1 text-left text-xs"
16270
16318
  }, formatLabel(preset.name, 11)))))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, {
@@ -17410,9 +17458,9 @@ function ModalityLoadBadge({
17410
17458
  if (!statusInfo.isHydrated) {
17411
17459
  return /*#__PURE__*/react.createElement("div", {
17412
17460
  "data-cy": `ModalityLoadBadge-${viewportId}`,
17413
- className: "flex h-6 cursor-default text-sm leading-6 text-white"
17461
+ className: "text-foreground flex h-6 cursor-default text-sm leading-6"
17414
17462
  }, /*#__PURE__*/react.createElement("div", {
17415
- className: "bg-customgray-100 flex min-w-[45px] items-center rounded-l-xl rounded-r p-1"
17463
+ className: "bg-popover flex min-w-[45px] items-center rounded-l-xl rounded-r p-1"
17416
17464
  }, /*#__PURE__*/react.createElement(StatusIcon, null), /*#__PURE__*/react.createElement("span", {
17417
17465
  className: "ml-1"
17418
17466
  }, statusInfo.type)), statusInfo.type !== 'SR' && /*#__PURE__*/react.createElement(ui_next_src/* ViewportActionButton */.N8H, {
@@ -18829,7 +18877,12 @@ const segmentationRepresentationModifiedCallback = async (synchronizerInstance,
18829
18877
  const sourceDisplaySetUIDs = extractDisplaySetUIDs(sourceViewportInfo);
18830
18878
  const targetDisplaySetUIDs = extractDisplaySetUIDs(targetViewportInfo);
18831
18879
  const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs);
18832
- if (!sharedDisplaySetExists && !viewport.getFrameOfReferenceUID()) {
18880
+ const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID();
18881
+ const sourceFrameOfReferenceUID = (0,esm.getEnabledElementByViewportId)(sourceViewportId)?.viewport?.getFrameOfReferenceUID();
18882
+ if (!sharedDisplaySetExists && !targetFrameOfReferenceUID) {
18883
+ return;
18884
+ }
18885
+ if (!sharedDisplaySetExists && targetFrameOfReferenceUID !== sourceFrameOfReferenceUID) {
18833
18886
  return;
18834
18887
  }
18835
18888
  const targetViewportRepresentation = segmentationService.getSegmentationRepresentations(targetViewportId, {
@@ -19196,11 +19249,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
19196
19249
  this.EVENTS = SegmentationService_EVENTS;
19197
19250
  this.destroy = () => {
19198
19251
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
19199
- esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationModifiedFromSource);
19252
+ esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
19200
19253
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
19201
19254
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
19202
19255
  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);
19256
+ esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
19204
19257
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
19205
19258
  this.reset();
19206
19259
  };
@@ -19261,6 +19314,16 @@ class SegmentationService extends src/* PubSubService */.Rc {
19261
19314
  viewportId
19262
19315
  });
19263
19316
  };
19317
+ this._onSegmentationRepresentationRemovedFromSource = evt => {
19318
+ const {
19319
+ segmentationId,
19320
+ viewportId
19321
+ } = evt.detail;
19322
+ this._broadcastEvent(this.EVENTS.SEGMENTATION_REPRESENTATION_REMOVED, {
19323
+ segmentationId,
19324
+ viewportId
19325
+ });
19326
+ };
19264
19327
  this._onSegmentationModifiedFromSource = evt => {
19265
19328
  const {
19266
19329
  segmentationId
@@ -19277,6 +19340,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
19277
19340
  segmentationId
19278
19341
  });
19279
19342
  };
19343
+ this._onSegmentationRemovedFromSource = evt => {
19344
+ const {
19345
+ segmentationId
19346
+ } = evt.detail;
19347
+ this._broadcastEvent(this.EVENTS.SEGMENTATION_REMOVED, {
19348
+ segmentationId
19349
+ });
19350
+ };
19280
19351
  this._onAnnotationCutMergeProcessCompletedFromSource = evt => {
19281
19352
  const {
19282
19353
  segmentationId
@@ -19482,6 +19553,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19482
19553
  },
19483
19554
  config: {
19484
19555
  label,
19556
+ fallbackLabel: `S:${displaySet.SeriesNumber} ${displaySet.Modality}`,
19485
19557
  segments: options?.segments && Object.keys(options.segments).length > 0 ? options.segments : {
19486
19558
  1: {
19487
19559
  label: `${i18n_src/* default */.A.t('Segment')} 1`,
@@ -19613,6 +19685,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19613
19685
  },
19614
19686
  config: {
19615
19687
  label: segDisplaySet.SeriesDescription,
19688
+ fallbackLabel: `S:${segDisplaySet.SeriesNumber} ${segDisplaySet.Modality}`,
19616
19689
  segments
19617
19690
  }
19618
19691
  };
@@ -19673,7 +19746,8 @@ class SegmentationService extends src/* PubSubService */.Rc {
19673
19746
  }
19674
19747
  },
19675
19748
  config: {
19676
- label: rtDisplaySet.SeriesDescription
19749
+ label: rtDisplaySet.SeriesDescription,
19750
+ fallbackLabel: `S:${rtDisplaySet.SeriesNumber} ${rtDisplaySet.Modality}`
19677
19751
  }
19678
19752
  };
19679
19753
  const segments = {};
@@ -20170,14 +20244,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
20170
20244
  }
20171
20245
  /**
20172
20246
  * Clears segmentation representations from the viewport.
20173
- * Unlike removeSegmentationRepresentations, this doesn't update
20247
+ * Unlike removeRepresentationsFromViewport, this doesn't update
20174
20248
  * removed display set and representation maps.
20175
20249
  * We track removed segmentations manually to avoid re-adding them
20176
20250
  * when the display set is added again.
20177
20251
  * @param viewportId - The viewport ID to clear segmentation representations from.
20178
20252
  */
20179
20253
  clearSegmentationRepresentations(viewportId) {
20180
- this.removeSegmentationRepresentations(viewportId);
20254
+ this.removeRepresentationsFromViewport(viewportId);
20181
20255
  }
20182
20256
 
20183
20257
  /**
@@ -20192,7 +20266,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20192
20266
  }
20193
20267
 
20194
20268
  /**
20195
- * It removes the segmentation representations from the viewport.
20269
+ * Removes segmentation representations from the viewport.
20196
20270
  * @param viewportId - The viewport id to remove the segmentation representations from.
20197
20271
  * @param specifier - The specifier to remove the segmentation representations.
20198
20272
  *
@@ -20202,7 +20276,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20202
20276
  * If a type specifier is provided, only the segmentation representation with the specified type are removed.
20203
20277
  * If both a segmentationId and type specifier are provided, only the segmentation representation with the specified segmentationId and type are removed.
20204
20278
  */
20205
- removeSegmentationRepresentations(viewportId, specifier = {}) {
20279
+ removeRepresentationsFromViewport(viewportId, specifier = {}) {
20206
20280
  dist_esm.segmentation.removeSegmentationRepresentations(viewportId, specifier);
20207
20281
  }
20208
20282
 
@@ -20558,6 +20632,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20558
20632
  id: id,
20559
20633
  segmentationId,
20560
20634
  label: segmentation.label,
20635
+ fallbackLabel: segmentation.fallbackLabel,
20561
20636
  active,
20562
20637
  type,
20563
20638
  visible,
@@ -20570,11 +20645,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
20570
20645
  }
20571
20646
  _initSegmentationService() {
20572
20647
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
20573
- esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationModifiedFromSource);
20648
+ esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
20574
20649
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
20575
20650
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
20576
20651
  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);
20652
+ esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
20578
20653
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
20579
20654
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, this._onAnnotationCutMergeProcessCompletedFromSource);
20580
20655
  }
@@ -20780,6 +20855,7 @@ const ORTHOGRAPHIC = 'orthographic';
20780
20855
  const VOLUME_3D = 'volume3d';
20781
20856
  const VIDEO = 'video';
20782
20857
  const WHOLESLIDE = 'wholeslide';
20858
+ const ECG = 'ecg';
20783
20859
  function getCornerstoneViewportType(viewportType, displaySets) {
20784
20860
  const lowerViewportType = displaySets?.[0]?.viewportType?.toLowerCase() || viewportType.toLowerCase();
20785
20861
  if (lowerViewportType === STACK) {
@@ -20791,13 +20867,16 @@ function getCornerstoneViewportType(viewportType, displaySets) {
20791
20867
  if (lowerViewportType === WHOLESLIDE) {
20792
20868
  return esm.Enums.ViewportType.WHOLE_SLIDE;
20793
20869
  }
20870
+ if (lowerViewportType === ECG) {
20871
+ return esm.Enums.ViewportType.ECG;
20872
+ }
20794
20873
  if (lowerViewportType === VOLUME || lowerViewportType === ORTHOGRAPHIC) {
20795
20874
  return esm.Enums.ViewportType.ORTHOGRAPHIC;
20796
20875
  }
20797
20876
  if (lowerViewportType === VOLUME_3D) {
20798
20877
  return esm.Enums.ViewportType.VOLUME_3D;
20799
20878
  }
20800
- throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide`);
20879
+ throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide, ecg`);
20801
20880
  }
20802
20881
  ;// ../../../extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts
20803
20882
  var _CornerstoneCacheService;
@@ -21104,15 +21183,24 @@ function getCornerstoneBlendMode(blendMode) {
21104
21183
  const AXIAL = 'axial';
21105
21184
  const SAGITTAL = 'sagittal';
21106
21185
  const CORONAL = 'coronal';
21186
+ const AXIAL_REFORMAT = 'axial_reformat';
21187
+ const SAGITTAL_REFORMAT = 'sagittal_reformat';
21188
+ const CORONAL_REFORMAT = 'coronal_reformat';
21107
21189
  function getCornerstoneOrientation(orientation) {
21108
21190
  if (orientation) {
21109
21191
  switch (orientation.toLowerCase()) {
21110
21192
  case AXIAL:
21111
21193
  return esm.Enums.OrientationAxis.AXIAL;
21194
+ case AXIAL_REFORMAT:
21195
+ return esm.Enums.OrientationAxis.AXIAL_REFORMAT;
21112
21196
  case SAGITTAL:
21113
21197
  return esm.Enums.OrientationAxis.SAGITTAL;
21198
+ case SAGITTAL_REFORMAT:
21199
+ return esm.Enums.OrientationAxis.SAGITTAL_REFORMAT;
21114
21200
  case CORONAL:
21115
21201
  return esm.Enums.OrientationAxis.CORONAL;
21202
+ case CORONAL_REFORMAT:
21203
+ return esm.Enums.OrientationAxis.CORONAL_REFORMAT;
21116
21204
  default:
21117
21205
  return esm.Enums.OrientationAxis.ACQUISITION;
21118
21206
  }
@@ -22072,6 +22160,15 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22072
22160
  /**
22073
22161
  * Sets the image data for the given viewport.
22074
22162
  */
22163
+ async _setEcgViewport(viewport, viewportData) {
22164
+ const [displaySet] = viewportData.data;
22165
+ const imageId = displaySet.imageIds?.[0];
22166
+ if (!imageId) {
22167
+ console.error('[CornerstoneViewportService] ECG display set has no imageId');
22168
+ return;
22169
+ }
22170
+ return viewport.setEcg(imageId);
22171
+ }
22075
22172
  async _setOtherViewport(viewport, viewportData, viewportInfo, _presentations = {}) {
22076
22173
  const [displaySet] = viewportData.data;
22077
22174
  return viewport.setDataIds(displaySet.imageIds, {
@@ -22140,32 +22237,25 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22140
22237
  if (initialImageIndexToUse === undefined || initialImageIndexToUse === null || initialImageIndexToUse < 0) {
22141
22238
  initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
22142
22239
  }
22143
- return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
22240
+ await viewport.setStack(imageIds, initialImageIndexToUse);
22241
+ viewport.setProperties({
22242
+ ...properties
22243
+ });
22244
+ this.setPresentations(viewport.id, presentations, viewportInfo);
22245
+ await this._addOverlayRepresentations(overlayProcessingResults);
22246
+ if (displayArea) {
22247
+ viewport.setDisplayArea(displayArea);
22248
+ }
22249
+ if (rotation) {
22144
22250
  viewport.setProperties({
22145
- ...properties
22251
+ rotation
22146
22252
  });
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
- });
22253
+ }
22254
+ if (flipHorizontal) {
22255
+ viewport.setCamera({
22256
+ flipHorizontal: true
22257
+ });
22258
+ }
22169
22259
  }
22170
22260
  _getInitialImageIndexForViewport(viewportInfo, imageIds) {
22171
22261
  const initialImageOptions = viewportInfo.getInitialImageOptions();
@@ -22389,15 +22479,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22389
22479
  });
22390
22480
  }
22391
22481
  await viewport.setVolumes(volumeInputArray);
22392
- if (overlayProcessingResults?.length) {
22393
- overlayProcessingResults.forEach(({
22394
- addOverlayFn
22395
- }) => {
22396
- if (addOverlayFn) {
22397
- addOverlayFn();
22398
- }
22399
- });
22400
- }
22482
+ await this._addOverlayRepresentations(overlayProcessingResults);
22401
22483
  viewport.render();
22402
22484
  volumesProperties.forEach(({
22403
22485
  properties,
@@ -22460,7 +22542,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22460
22542
  const {
22461
22543
  predecessorImageId
22462
22544
  } = displaySet;
22463
- segmentationService.addSegmentationRepresentation(viewport.id, {
22545
+ const segmentationRepresentationPromise = segmentationService.addSegmentationRepresentation(viewport.id, {
22464
22546
  segmentationId,
22465
22547
  predecessorImageId,
22466
22548
  type: representationType,
@@ -22468,11 +22550,21 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22468
22550
  blendMode: viewport?.getBlendMode?.() === 1 ? dist_esm_enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
22469
22551
  }
22470
22552
  });
22471
-
22472
22553
  // store the segmentation presentation id in the viewport info
22473
22554
  this.storePresentation({
22474
22555
  viewportId: viewport.id
22475
22556
  });
22557
+ return segmentationRepresentationPromise;
22558
+ }
22559
+ async _addOverlayRepresentations(overlayProcessingResults) {
22560
+ if (!overlayProcessingResults?.length) {
22561
+ return;
22562
+ }
22563
+ for (const overlayProcessingResult of overlayProcessingResults) {
22564
+ if (overlayProcessingResult?.addOverlayFn) {
22565
+ await overlayProcessingResult.addOverlayFn();
22566
+ }
22567
+ }
22476
22568
  }
22477
22569
 
22478
22570
  // Todo: keepCamera is an interim solution until we have a better solution for
@@ -22507,6 +22599,9 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22507
22599
  if ([esm.VolumeViewport, esm.VolumeViewport3D].some(type => viewport instanceof type)) {
22508
22600
  return this._setVolumeViewport(viewport, viewportData, viewportInfo, presentations);
22509
22601
  }
22602
+ if (viewport instanceof esm.ECGViewport) {
22603
+ return this._setEcgViewport(viewport, viewportData);
22604
+ }
22510
22605
  return this._setOtherViewport(viewport, viewportData, viewportInfo, presentations);
22511
22606
  }
22512
22607
 
@@ -22549,8 +22644,8 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22549
22644
  if (!displaySet) {
22550
22645
  return;
22551
22646
  }
22552
- if (displaySet.frameOfReferenceUID) {
22553
- return displaySet.frameOfReferenceUID;
22647
+ if (displaySet.FrameOfReferenceUID) {
22648
+ return displaySet.FrameOfReferenceUID;
22554
22649
  }
22555
22650
  if (displaySet.Modality === 'SEG') {
22556
22651
  const {
@@ -22728,6 +22823,8 @@ CornerstoneViewportService.REGISTRATION = {
22728
22823
  }
22729
22824
  };
22730
22825
  /* harmony default export */ const ViewportService_CornerstoneViewportService = (CornerstoneViewportService);
22826
+ // EXTERNAL MODULE: ../../../extensions/cornerstone/src/utils/getDataIdForViewport.ts
22827
+ var getDataIdForViewport = __webpack_require__(67142);
22731
22828
  ;// ../../../extensions/cornerstone/src/types/Colorbar.ts
22732
22829
  // Position options
22733
22830
 
@@ -22770,6 +22867,7 @@ var _ColorbarService;
22770
22867
 
22771
22868
 
22772
22869
 
22870
+
22773
22871
  class ColorbarService extends src/* PubSubService */.Rc {
22774
22872
  constructor(servicesManager) {
22775
22873
  super(ColorbarService.EVENTS);
@@ -22793,23 +22891,6 @@ class ColorbarService extends src/* PubSubService */.Rc {
22793
22891
  this.servicesManager = servicesManager;
22794
22892
  }
22795
22893
 
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
22894
  /**
22814
22895
  * Adds a colorbar to a specific viewport identified by `viewportId`, using the provided `displaySetInstanceUIDs` and `options`.
22815
22896
  * This method prepares the colorbar state that will be used by the ViewportColorbarsContainer component.
@@ -22841,7 +22922,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
22841
22922
  if (displaySet.isOverlayDisplaySet) {
22842
22923
  return;
22843
22924
  }
22844
- const dataId = this.getDataIdForViewport(viewport, displaySetInstanceUID);
22925
+ const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
22845
22926
  const properties = dataId ? viewport.getProperties(dataId) : viewport.getProperties();
22846
22927
  const colormap = properties?.colormap;
22847
22928
  if (activeColormapName && !colormap) {
@@ -22979,7 +23060,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
22979
23060
  }
22980
23061
 
22981
23062
  // Get the appropriate dataId for this viewport/displaySet combination
22982
- const dataId = this.getDataIdForViewport(viewport, displaySetInstanceUID);
23063
+ const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
22983
23064
 
22984
23065
  // Set properties with or without dataId based on what the viewport supports
22985
23066
  viewport.setProperties({
@@ -23249,12 +23330,114 @@ const createFrameViewSynchronizer = synchronizerName => {
23249
23330
 
23250
23331
  // EXTERNAL MODULE: ../../../node_modules/dcmjs/build/dcmjs.es.js
23251
23332
  var dcmjs_es = __webpack_require__(5842);
23333
+ ;// ../../../extensions/cornerstone/src/utils/ecgMetadata.ts
23334
+ /**
23335
+ * Decode a multiplexed Int16 buffer into per-channel arrays.
23336
+ * Layout: sample0ch0, sample0ch1 ... sample0chN, sample1ch0, …
23337
+ * Note: DICOM ECG data is canonically SS (signed short). The sampleInterpretation
23338
+ * field is forwarded to ECGViewport for its own use; the raw buffer is always
23339
+ * treated as Int16 because Cornerstone ECGViewport expects Int16Array[].
23340
+ */
23341
+ function decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples) {
23342
+ const src = new Int16Array(buffer);
23343
+ const channels = [];
23344
+ for (let ch = 0; ch < numberOfChannels; ch++) {
23345
+ const out = new Int16Array(numberOfSamples);
23346
+ for (let s = 0; s < numberOfSamples; s++) {
23347
+ out[s] = src[s * numberOfChannels + ch];
23348
+ }
23349
+ channels.push(out);
23350
+ }
23351
+ return channels;
23352
+ }
23353
+
23354
+ /**
23355
+ * Decode a base64 InlineBinary string into a raw ArrayBuffer.
23356
+ */
23357
+ function base64ToArrayBuffer(base64) {
23358
+ const binaryStr = atob(base64);
23359
+ const bytes = new Uint8Array(binaryStr.length);
23360
+ for (let i = 0; i < binaryStr.length; i++) {
23361
+ bytes[i] = binaryStr.charCodeAt(i);
23362
+ }
23363
+ return bytes.buffer;
23364
+ }
23365
+ /**
23366
+ * Parse the naturalized DICOM instance's WaveformSequence and build the ecgModule
23367
+ * that Cornerstone's ECGViewport.setEcg() expects via
23368
+ * metaData.get(MetadataModules.ECG, imageId).
23369
+ *
23370
+ * Returns null if the instance has no WaveformSequence.
23371
+ */
23372
+ function buildEcgModule(instance, userAuthenticationService) {
23373
+ const waveformGroups = instance?.WaveformSequence;
23374
+ if (!waveformGroups?.length) {
23375
+ return null;
23376
+ }
23377
+
23378
+ // Use the first (and typically only) multiplex group
23379
+ const group = waveformGroups[0];
23380
+ const numberOfChannels = group.NumberOfWaveformChannels ?? 0;
23381
+ const numberOfSamples = group.NumberOfWaveformSamples ?? 0;
23382
+ const samplingFrequency = group.SamplingFrequency ?? 1;
23383
+ const bitsAllocated = group.WaveformBitsAllocated ?? 16;
23384
+ const sampleInterpretation = group.WaveformSampleInterpretation ?? 'SS';
23385
+ const multiplexGroupLabel = group.MultiplexGroupLabel ?? '';
23386
+ const channelDefinitionSequence = (group.ChannelDefinitionSequence ?? []).map(ch => ({
23387
+ channelSourceSequence: {
23388
+ codeMeaning: ch?.ChannelSourceSequence?.[0]?.CodeMeaning ?? ch?.ChannelSourceSequence?.[0]?.codeMeaning ?? ''
23389
+ }
23390
+ }));
23391
+ const retrieveBulkData = async () => {
23392
+ const waveformData = group.WaveformData;
23393
+ if (!waveformData) {
23394
+ console.warn('[ECGViewport] No WaveformData found on instance');
23395
+ return [];
23396
+ }
23397
+ let buffer;
23398
+ if (waveformData.InlineBinary) {
23399
+ buffer = base64ToArrayBuffer(waveformData.InlineBinary);
23400
+ } else if (waveformData.BulkDataURI) {
23401
+ const headers = {
23402
+ Accept: 'application/octet-stream'
23403
+ };
23404
+ const authHeader = userAuthenticationService?.getAuthorizationHeader?.();
23405
+ if (authHeader) {
23406
+ Object.assign(headers, authHeader);
23407
+ }
23408
+ const response = await fetch(waveformData.BulkDataURI, {
23409
+ headers
23410
+ });
23411
+ if (!response.ok) {
23412
+ throw new Error(`[ECGViewport] Failed to fetch waveform BulkDataURI: ${response.status}`);
23413
+ }
23414
+ buffer = await response.arrayBuffer();
23415
+ } else {
23416
+ console.warn('[ECGViewport] WaveformData has no InlineBinary or BulkDataURI');
23417
+ return [];
23418
+ }
23419
+ return decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples);
23420
+ };
23421
+ return {
23422
+ numberOfWaveformChannels: numberOfChannels,
23423
+ numberOfWaveformSamples: numberOfSamples,
23424
+ samplingFrequency,
23425
+ waveformBitsAllocated: bitsAllocated,
23426
+ waveformSampleInterpretation: sampleInterpretation,
23427
+ multiplexGroupLabel,
23428
+ channelDefinitionSequence,
23429
+ waveformData: {
23430
+ retrieveBulkData
23431
+ }
23432
+ };
23433
+ }
23252
23434
  ;// ../../../extensions/cornerstone/src/getSopClassHandlerModule.js
23253
23435
 
23254
23436
 
23255
23437
 
23256
23438
 
23257
23439
 
23440
+
23258
23441
  const {
23259
23442
  MetadataModules
23260
23443
  } = esm.Enums;
@@ -23265,9 +23448,9 @@ const {
23265
23448
  denaturalizeDataset
23266
23449
  } = dcmjs_es/* default.data */.Ay.data.DicomMetaDictionary;
23267
23450
  const {
23268
- transferDenaturalizedDataset,
23269
- fixMultiValueKeys
23270
- } = default_src.dicomWebUtils;
23451
+ /* transferDenaturalizedDataset */ "If": transferDenaturalizedDataset,
23452
+ /* fixMultiValueKeys */ "Uk": fixMultiValueKeys
23453
+ } = default_src/* dicomWebUtils */.CA;
23271
23454
  const SOP_CLASS_UIDS = {
23272
23455
  VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: '1.2.840.10008.5.1.4.1.1.77.1.6'
23273
23456
  };
@@ -23393,8 +23576,92 @@ function getDicomMicroscopySopClassHandler({
23393
23576
  getDisplaySetsFromSeries
23394
23577
  };
23395
23578
  }
23579
+
23580
+ /**
23581
+ * DICOM Waveform SOP Class UIDs for ECG / cardiac electrophysiology.
23582
+ * Reference: https://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.5.html
23583
+ */
23584
+ const ECG_SOP_CLASS_UIDS = {
23585
+ TWELVE_LEAD_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.1',
23586
+ GENERAL_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.2',
23587
+ AMBULATORY_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.3',
23588
+ HEMODYNAMIC_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.2.1',
23589
+ CARDIAC_ELECTROPHYSIOLOGY_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.3.1'
23590
+ };
23591
+ const ecgSopClassUids = Object.values(ECG_SOP_CLASS_UIDS);
23592
+ const DicomEcgSOPClassHandlerId = '@ohif/extension-cornerstone.sopClassHandlerModule.DicomEcgSopClassHandler';
23593
+ function _getEcgDisplaySetsFromSeries(instances, servicesManager) {
23594
+ const {
23595
+ userAuthenticationService
23596
+ } = servicesManager.services;
23597
+ return instances.map(instance => {
23598
+ const {
23599
+ Modality,
23600
+ SOPInstanceUID
23601
+ } = instance;
23602
+ const {
23603
+ SeriesDescription,
23604
+ SeriesNumber,
23605
+ SeriesDate
23606
+ } = instance;
23607
+ const {
23608
+ SeriesInstanceUID,
23609
+ StudyInstanceUID,
23610
+ SOPClassUID
23611
+ } = instance;
23612
+ const imageId = instance.imageId;
23613
+
23614
+ // Register ECG metadata in the OHIF metadata provider so that
23615
+ // Cornerstone's ECGViewport can retrieve it via metaData.get('ecgModule', imageId).
23616
+ if (imageId) {
23617
+ const ecgModule = buildEcgModule(instance, userAuthenticationService);
23618
+ if (ecgModule) {
23619
+ esm.utilities.genericMetadataProvider.addRaw(imageId, {
23620
+ type: MetadataModules.ECG,
23621
+ metadata: ecgModule
23622
+ });
23623
+ }
23624
+ }
23625
+ return {
23626
+ Modality,
23627
+ displaySetInstanceUID: getSopClassHandlerModule_utils.guid(),
23628
+ SeriesDescription,
23629
+ SeriesNumber,
23630
+ SeriesDate,
23631
+ SOPInstanceUID,
23632
+ SeriesInstanceUID,
23633
+ StudyInstanceUID,
23634
+ SOPClassHandlerId: DicomEcgSOPClassHandlerId,
23635
+ SOPClassUID,
23636
+ referencedImages: null,
23637
+ measurements: null,
23638
+ viewportType: esm.Enums.ViewportType.ECG,
23639
+ instances: [instance],
23640
+ instance,
23641
+ thumbnailSrc: null,
23642
+ isDerivedDisplaySet: false,
23643
+ isLoaded: false,
23644
+ sopClassUids: ecgSopClassUids,
23645
+ numImageFrames: 0,
23646
+ numInstances: 1,
23647
+ imageIds: imageId ? [imageId] : [],
23648
+ supportsWindowLevel: false,
23649
+ label: SeriesDescription || 'ECG'
23650
+ };
23651
+ });
23652
+ }
23653
+ function getDicomEcgSopClassHandler({
23654
+ servicesManager
23655
+ }) {
23656
+ const getDisplaySetsFromSeries = instances => _getEcgDisplaySetsFromSeries(instances, servicesManager);
23657
+ return {
23658
+ name: 'DicomEcgSopClassHandler',
23659
+ sopClassUids: ecgSopClassUids,
23660
+ getDisplaySetsFromSeries
23661
+ };
23662
+ }
23396
23663
  function getSopClassHandlerModule(params) {
23397
- return [getDicomMicroscopySopClassHandler(params)];
23664
+ return [getDicomMicroscopySopClassHandler(params), getDicomEcgSopClassHandler(params)];
23398
23665
  }
23399
23666
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/hooks/useActiveViewportSegmentationRepresentations.ts
23400
23667
  var useActiveViewportSegmentationRepresentations = __webpack_require__(9234);
@@ -23424,7 +23691,7 @@ function SegmentationUtilityButton(props) {
23424
23691
  isActive,
23425
23692
  id
23426
23693
  } = props;
23427
- const activeSegmentationUtility = (0,default_src.useUIStateStore)(store => store.uiState.activeSegmentationUtility);
23694
+ const activeSegmentationUtility = (0,default_src/* useUIStateStore */.FS)(store => store.uiState.activeSegmentationUtility);
23428
23695
  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
23696
  const handleMouseDownCapture = (0,react.useCallback)(event => {
23430
23697
  if (activeSegmentationUtility === id) {
@@ -23555,7 +23822,7 @@ function PanelSegmentation({
23555
23822
  segmentationsWithRepresentations,
23556
23823
  disabled
23557
23824
  } = (0,useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c)();
23558
- const setUIState = (0,default_src.useUIStateStore)(store => store.setUIState);
23825
+ const setUIState = (0,default_src/* useUIStateStore */.FS)(store => store.setUIState);
23559
23826
 
23560
23827
  // useEffect for handling clicks on any of the non-active viewports.
23561
23828
  // The ViewportGrid stops the propagation of pointer/mouse events
@@ -23816,7 +24083,7 @@ function PanelSegmentation({
23816
24083
  IconContainer: components_SegmentationUtilityButton
23817
24084
  }, /*#__PURE__*/react.createElement("div", {
23818
24085
  className: "flex flex-wrap gap-[3px] bg-transparent pb-[2px] pl-[8px] pt-[6px]"
23819
- }, /*#__PURE__*/react.createElement(default_src.Toolbar, {
24086
+ }, /*#__PURE__*/react.createElement(default_src/* Toolbar */.M7, {
23820
24087
  buttonSection: buttonSection
23821
24088
  })));
23822
24089
  };
@@ -24343,12 +24610,12 @@ function DefaultAccordion(props) {
24343
24610
  if (!allChildren || !groups) {
24344
24611
  return null;
24345
24612
  }
24346
- if (Boolean(asChild)) {
24613
+ if (asChild) {
24347
24614
  return /*#__PURE__*/react.cloneElement(props.children, props);
24348
24615
  }
24349
24616
  return /*#__PURE__*/react.createElement(ui_next_src/* Accordion */.nD3, {
24350
24617
  type: grouping.type || 'multiple',
24351
- className: "text-white",
24618
+ className: "text-foreground",
24352
24619
  defaultValue: defaultValue
24353
24620
  }, [...groups.entries()].map(([key, group]) => {
24354
24621
  return /*#__PURE__*/react.createElement(ui_next_src/* AccordionItem */.AsP, {
@@ -24826,7 +25093,7 @@ function PanelMeasurement(props) {
24826
25093
  return EmptyComponent ? /*#__PURE__*/react.createElement(EmptyComponent, {
24827
25094
  items: displayMeasurements
24828
25095
  }) : /*#__PURE__*/react.createElement("span", {
24829
- className: "text-white"
25096
+ className: "text-foreground"
24830
25097
  }, "No Measurements");
24831
25098
  }
24832
25099
  if (children) {
@@ -24891,7 +25158,7 @@ const getPanelModule = ({
24891
25158
  } = (0,es/* useTranslation */.Bd)('SegmentationPanel');
24892
25159
  const tKey = `${props.segmentationRepresentationTypes?.[0] ?? 'Segmentation'} tools`;
24893
25160
  const tValue = t(tKey);
24894
- return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src.Toolbox, {
25161
+ return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src/* Toolbox */.OO, {
24895
25162
  buttonSectionId: toolSectionMap[props.segmentationRepresentationTypes?.[0]],
24896
25163
  title: tValue
24897
25164
  }), /*#__PURE__*/react.createElement(PanelSegmentation, {
@@ -25245,7 +25512,7 @@ function promptHydrationDialog({
25245
25512
  customizationService
25246
25513
  } = servicesManager.services;
25247
25514
  const extensionManager = servicesManager._extensionManager;
25248
- const appConfig = extensionManager._appConfig;
25515
+ const appConfig = extensionManager.appConfig;
25249
25516
 
25250
25517
  // Todo: make this use enum from the extension, we should move the enum
25251
25518
  const standardMode = appConfig?.measurementTrackingMode === 'standard';
@@ -25262,20 +25529,30 @@ function promptHydrationDialog({
25262
25529
  if (type === HydrationType.SEG) {
25263
25530
  // SEG needs setTimeout
25264
25531
  window.setTimeout(async () => {
25265
- const isHydrated = await hydrateCallback({
25266
- segDisplaySet: displaySet,
25267
- viewportId
25268
- });
25269
- resolve(isHydrated);
25532
+ try {
25533
+ const isHydrated = await hydrateCallback({
25534
+ segDisplaySet: displaySet,
25535
+ viewportId
25536
+ });
25537
+ resolve(isHydrated);
25538
+ } catch (error) {
25539
+ reject(error);
25540
+ }
25270
25541
  }, 0);
25271
25542
  } else if (type === HydrationType.RTSTRUCT) {
25272
25543
  // RT hydration
25273
- const isHydrated = await hydrateCallback({
25274
- rtDisplaySet: displaySet,
25275
- viewportId,
25276
- servicesManager
25277
- });
25278
- resolve(isHydrated);
25544
+ window.setTimeout(async () => {
25545
+ try {
25546
+ const isHydrated = await hydrateCallback({
25547
+ rtDisplaySet: displaySet,
25548
+ viewportId,
25549
+ servicesManager
25550
+ });
25551
+ resolve(isHydrated);
25552
+ } catch (error) {
25553
+ reject(error);
25554
+ }
25555
+ }, 0);
25279
25556
  } else if (type === HydrationType.SR) {
25280
25557
  // SR has a different result structure
25281
25558
  const hydrationResult = await hydrateCallback(displaySet);
@@ -25368,7 +25645,8 @@ const setUpSegmentationEventHandlers = ({
25368
25645
  const {
25369
25646
  segmentationService,
25370
25647
  customizationService,
25371
- displaySetService
25648
+ displaySetService,
25649
+ viewportGridService
25372
25650
  } = servicesManager.services;
25373
25651
  const {
25374
25652
  unsubscribe: unsubscribeSegmentationDataModifiedHandler
@@ -25413,12 +25691,42 @@ const setUpSegmentationEventHandlers = ({
25413
25691
  };
25414
25692
  displaySetService.addDisplaySets(segmentationDisplaySet);
25415
25693
  });
25694
+ const {
25695
+ unsubscribe: unsubscribeSegmentationRemoved
25696
+ } = segmentationService.subscribe(segmentationService.EVENTS.SEGMENTATION_REMOVED, ({
25697
+ segmentationId
25698
+ }) => {
25699
+ const displaySet = displaySetService.getDisplaySetByUID(segmentationId);
25700
+
25701
+ // Remove the display set layer from all viewports that have it
25702
+ if (displaySet) {
25703
+ const state = viewportGridService.getState();
25704
+ const viewports = state.viewports;
25705
+
25706
+ // Find all viewports that contain this segmentation's display set as a layer
25707
+ for (const [viewportId, viewport] of viewports.entries()) {
25708
+ const displaySetInstanceUIDs = viewport.displaySetInstanceUIDs || [];
25709
+ if (displaySetInstanceUIDs.includes(segmentationId)) {
25710
+ // Remove the display set layer from this viewport
25711
+ commandsManager.runCommand('removeDisplaySetLayer', {
25712
+ viewportId,
25713
+ displaySetInstanceUID: segmentationId
25714
+ });
25715
+ }
25716
+ }
25717
+
25718
+ // Delete the display set from the service if it was made in client
25719
+ if (displaySet.madeInClient) {
25720
+ displaySetService.deleteDisplaySet(segmentationId);
25721
+ }
25722
+ }
25723
+ });
25416
25724
  const {
25417
25725
  unsubscribeSelectedSegmentationsForViewportEvents
25418
25726
  } = setUpSelectedSegmentationsForViewportHandler({
25419
25727
  segmentationService
25420
25728
  });
25421
- const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, ...unsubscribeSelectedSegmentationsForViewportEvents];
25729
+ const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, unsubscribeSegmentationRemoved, ...unsubscribeSelectedSegmentationsForViewportEvents];
25422
25730
  return {
25423
25731
  unsubscriptions
25424
25732
  };
@@ -25561,7 +25869,7 @@ function PanelAccordionTrigger(props) {
25561
25869
  }, /*#__PURE__*/react.createElement("button", {
25562
25870
  onClick: onClickDefault.bind(props)
25563
25871
  }, /*#__PURE__*/react.createElement("span", {
25564
- className: `inline-flex rounded-l border-r border-black ${isActive ? 'bg-highlight' : 'bg-muted'}`
25872
+ className: `inline-flex rounded-l border-r border-background ${isActive ? 'bg-highlight' : 'bg-muted'}`
25565
25873
  }, count !== undefined ? /*#__PURE__*/react.createElement("span", {
25566
25874
  className: "px-2"
25567
25875
  }, count) : null, colorHex && /*#__PURE__*/react.createElement(ui_next_src/* ColorCircle */.cd8, {
@@ -25909,7 +26217,7 @@ const cornerstoneExtension = {
25909
26217
  useLutPresentationStore/* useLutPresentationStore */.I.getState().clearLutPresentationStore();
25910
26218
  usePositionPresentationStore/* usePositionPresentationStore */.q.getState().clearPositionPresentationStore();
25911
26219
  useSynchronizersStore/* useSynchronizersStore */.U.getState().clearSynchronizersStore();
25912
- default_src.useToggleOneUpViewportGridStore.getState().clearToggleOneUpViewportGridStore();
26220
+ default_src/* useToggleOneUpViewportGridStore */.Yd.getState().clearToggleOneUpViewportGridStore();
25913
26221
  useSegmentationPresentationStore/* useSegmentationPresentationStore */.v.getState().clearSegmentationPresentationStore();
25914
26222
  useSelectedSegmentationsForViewportStore.getState().clearSelectedSegmentationsForViewportStore();
25915
26223
  segmentationService.removeAllSegmentations();
@@ -26000,10 +26308,10 @@ const cornerstoneExtension = {
26000
26308
 
26001
26309
  /* harmony default export */ const cornerstone_src = (cornerstoneExtension);
26002
26310
 
26003
- /***/ }),
26311
+ /***/ },
26004
26312
 
26005
- /***/ 71353:
26006
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26313
+ /***/ 71353
26314
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26007
26315
 
26008
26316
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26009
26317
  /* harmony export */ cL: () => (/* binding */ reset),
@@ -26042,10 +26350,10 @@ const reset = () => {
26042
26350
  };
26043
26351
 
26044
26352
 
26045
- /***/ }),
26353
+ /***/ },
26046
26354
 
26047
- /***/ 46026:
26048
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26355
+ /***/ 46026
26356
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26049
26357
 
26050
26358
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26051
26359
  /* harmony export */ FG: () => (/* binding */ JOIN_STR),
@@ -26085,10 +26393,10 @@ const addUniqueIndex = (arr, key, viewports, isUpdatingSameViewport) => {
26085
26393
  };
26086
26394
 
26087
26395
 
26088
- /***/ }),
26396
+ /***/ },
26089
26397
 
26090
- /***/ 10182:
26091
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26398
+ /***/ 10182
26399
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26092
26400
 
26093
26401
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26094
26402
  /* harmony export */ I: () => (/* binding */ useLutPresentationStore)
@@ -26200,10 +26508,10 @@ const useLutPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .creat
26200
26508
  name: 'LutPresentationStore'
26201
26509
  }) : createLutPresentationStore);
26202
26510
 
26203
- /***/ }),
26511
+ /***/ },
26204
26512
 
26205
- /***/ 44646:
26206
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26513
+ /***/ 44646
26514
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26207
26515
 
26208
26516
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26209
26517
  /* harmony export */ q: () => (/* binding */ usePositionPresentationStore)
@@ -26311,10 +26619,10 @@ const usePositionPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .
26311
26619
  name: 'PositionPresentationStore'
26312
26620
  }) : createPositionPresentationStore);
26313
26621
 
26314
- /***/ }),
26622
+ /***/ },
26315
26623
 
26316
- /***/ 2847:
26317
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26624
+ /***/ 2847
26625
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26318
26626
 
26319
26627
 
26320
26628
  // EXPORTS
@@ -26520,10 +26828,10 @@ const useSegmentationPresentationStore = (0,esm/* create */.vt)()(DEBUG_STORE ?
26520
26828
  name: 'Segmentation Presentation Store'
26521
26829
  }) : createSegmentationPresentationStore);
26522
26830
 
26523
- /***/ }),
26831
+ /***/ },
26524
26832
 
26525
- /***/ 68578:
26526
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26833
+ /***/ 68578
26834
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26527
26835
 
26528
26836
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26529
26837
  /* harmony export */ U: () => (/* binding */ useSynchronizersStore)
@@ -26584,6 +26892,32 @@ const useSynchronizersStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .create
26584
26892
  name: 'SynchronizersStore'
26585
26893
  }) : createSynchronizersStore);
26586
26894
 
26587
- /***/ })
26895
+ /***/ },
26896
+
26897
+ /***/ 67142
26898
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26899
+
26900
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26901
+ /* harmony export */ V: () => (/* binding */ getDataIdForViewport)
26902
+ /* harmony export */ });
26903
+ /**
26904
+ * Resolves the data ID (e.g. volumeId) for a viewport and display set.
26905
+ * For viewports with multiple volumes/actors, returns the id that matches the display set; otherwise undefined.
26906
+ * Use this to call viewport.getProperties(dataId) in a viewport-type-agnostic way.
26907
+ *
26908
+ * @param viewport - Viewport instance (stack, volume, or future types with optional getAllVolumeIds)
26909
+ * @param displaySetInstanceUID - Display set instance UID to match
26910
+ * @returns volumeId (or equivalent) for multi-actor viewports, undefined for single-actor
26911
+ */
26912
+ function getDataIdForViewport(viewport, displaySetInstanceUID) {
26913
+ const vp = viewport;
26914
+ if (typeof vp.getAllVolumeIds !== 'function') {
26915
+ return undefined;
26916
+ }
26917
+ const volumeIds = vp.getAllVolumeIds() || [];
26918
+ return volumeIds.length > 0 ? volumeIds.find(id => id.includes(displaySetInstanceUID)) ?? undefined : undefined;
26919
+ }
26920
+
26921
+ /***/ }
26588
26922
 
26589
26923
  }]);