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

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 (72) hide show
  1. package/dist/{1459.bundle.075e535250e3d4779923.js → 1459.bundle.4ad39e2c21e35cb2be1c.js} +5 -6
  2. package/dist/{1608.bundle.0687c661f1c9edfb3b8a.js → 1608.bundle.26306ea38618db59eff7.js} +12 -12
  3. package/dist/{1927.bundle.3050588e95f43cf57cdd.js → 1927.bundle.be67b3aafe238ca9f191.js} +27 -38
  4. package/dist/{1933.bundle.317997210b6a51079753.js → 1933.bundle.82822511235016082da4.js} +32 -27
  5. package/dist/{2018.bundle.31d14d6f9fb764b51bda.js → 2018.bundle.6f06faf8d0a5c91f5e7c.js} +18 -19
  6. package/dist/{6409.bundle.b36048896cb11c8571fb.js → 2075.bundle.23265b8e7597c398db4f.js} +327 -256
  7. package/dist/{2108.bundle.e84aa8d858d8c4f2413e.js → 2108.bundle.aea8d3b39486dd5ab39e.js} +569 -558
  8. package/dist/{213.bundle.363f9a3eb6c0d33e3921.js → 213.bundle.d8a8ffeec432cd8363c0.js} +3 -5
  9. package/dist/{2424.bundle.aa7f4df6cba71b817c87.js → 2424.bundle.c602ad458e7902f7f555.js} +3 -5
  10. package/dist/{2516.bundle.1ea0988d309a757bb6da.js → 2516.bundle.f62228e9a800de8d4b31.js} +6 -6
  11. package/dist/{2701.bundle.12bd01a80a9f8ea4cd94.js → 2701.bundle.6873805ddfdccc7a8b1e.js} +10 -10
  12. package/dist/{9195.bundle.adf6a548b6f7ae279c09.js → 2851.bundle.123d7f6fa1186ac1308a.js} +384 -169
  13. package/dist/{1730.bundle.1d137db2556d538263fb.js → 3138.bundle.bc81953147e0c5f3b23f.js} +16 -310
  14. package/dist/{3461.bundle.7024d5e66d12b4069031.js → 3461.bundle.f65494e79c37a14bc206.js} +131 -107
  15. package/dist/{147.bundle.37d627289453cb6c3937.js → 3754.bundle.fd4b67c2a29c4bc4a840.js} +486 -49
  16. package/dist/{4202.bundle.5a0f8e4004c5d8a68548.js → 4202.bundle.4fcd0de412907efd5b53.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.75bf28fe32a927130dec.js} +10 -305
  20. package/dist/{6347.bundle.784c48912700f281de1d.js → 4579.bundle.0a6b2f49a7e136a79e37.js} +561 -649
  21. package/dist/{4819.bundle.0c37918802ef7805586f.js → 4819.bundle.23965159795eaeb1ca1b.js} +39 -39
  22. package/dist/{4775.bundle.5d6203a2991902544266.js → 5015.bundle.54d7fda0f8e819aaa578.js} +29 -333
  23. package/dist/{5028.bundle.2cd4d2253b47845e6634.js → 5028.bundle.b806370179a0f878527b.js} +11 -13
  24. package/dist/{5261.bundle.6e1a017f8f1027557f5b.js → 5261.bundle.2655560097e9250eac44.js} +412 -345
  25. package/dist/{5457.bundle.15d4adb3ca43c45b044d.js → 5457.bundle.d1e9be8eab20c1620624.js} +16 -23
  26. package/dist/{5485.bundle.b9764a7846d57ee5710d.js → 5485.bundle.7de6ed76c9bf762fd395.js} +20 -32
  27. package/dist/{5491.bundle.2e01dd7ad29e4cc01bc1.js → 5491.bundle.4866d2ecb20dd089e071.js} +54 -51
  28. package/dist/{5802.bundle.3bf5e6b3ab330a594a47.js → 5802.bundle.26f84db0ff8851532c36.js} +79 -20
  29. package/dist/5802.css +1 -1
  30. package/dist/{5830.bundle.b073c265c4fcea1afff3.js → 5830.bundle.791019deddd536980a11.js} +3 -3
  31. package/dist/{5858.bundle.ff6b340cf7457db76a1a.js → 5858.bundle.466e58128de344ab53f3.js} +90 -86
  32. package/dist/{6027.bundle.55f4bf16015381255f33.js → 6027.bundle.11c8ba4581dca8a82b91.js} +3 -5
  33. package/dist/{6354.bundle.c387737dc09c9cab4ff2.js → 6354.bundle.929febcf6d326e582e00.js} +151 -140
  34. package/dist/{6376.bundle.9cb74d7bc08476e2f1a7.js → 6376.bundle.738c873196491232acb6.js} +6 -6
  35. package/dist/{2842.bundle.860b9f10fcdd9656947a.js → 6386.bundle.5d82d1f41d1c37a0358d.js} +904 -2298
  36. package/dist/6939.bundle.41fbdef87597b5172ec6.js +3 -3
  37. package/dist/{7159.bundle.a5991a5d4f0dd8f1c95f.js → 7159.bundle.fb9df255868960f69765.js} +7 -5
  38. package/dist/{3081.bundle.f0df1c7d93ef4be29102.js → 7166.bundle.6334b7a549c8d1f58bfd.js} +825 -410
  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.d7571b9b1bdd3c712fa7.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.7ff9f067007c6fc02eff.js} +71 -66
  47. package/dist/{6163.bundle.18484c031c76e3835a71.js → 8499.bundle.b0d3892bff3f3163f747.js} +7 -302
  48. package/dist/8499.css +2 -0
  49. package/dist/{85.bundle.173a5ab4b47890e2f013.js → 85.bundle.203f56fd4f235891345a.js} +3 -5
  50. package/dist/{8558.bundle.52d7001a86845c8a91b8.js → 8558.bundle.ae26725ef258ef186524.js} +15 -309
  51. package/dist/{8583.bundle.e899badfa6f91f22b2f3.js → 8583.bundle.f56d7ead5b46d8d6f294.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.8c450e8d65a78a5afcd3.js} +10 -10
  56. package/dist/{9862.bundle.3a8958a82c572015d25d.js → 9862.bundle.a5f7925840868fa4ecdb.js} +8 -6
  57. package/dist/{9927.bundle.0e4c7a7682b7acad3060.js → 9927.bundle.ceb2c44737524314f168.js} +4 -6
  58. package/dist/app-config.js +12 -0
  59. package/dist/{app.bundle.62d84a3df6ec149a44a6.js → app.bundle.97f04c5d27e5017d698b.js} +100613 -97645
  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/{147.css → 3754.css} +0 -0
  71. /package/dist/{3343.css → 4972.css} +0 -0
  72. /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([[7166],{
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 + 3085 modules
29
+ var src = __webpack_require__(564);
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__(564);
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 + 3085 modules
502
+ var ui_next_src = __webpack_require__(564);
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;
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);
1018
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
+ /***/ 87166
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 + 3085 modules
7428
+ var ui_next_src = __webpack_require__(564);
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
@@ -9157,6 +9082,34 @@ function ViewportDownloadFormNew({
9157
9082
  value: 'Not For Diagnostic Use'
9158
9083
  }
9159
9084
  });
9085
+ ;// ../../../extensions/cornerstone/src/customizations/viewportScrollbarCustomization.tsx
9086
+ /**
9087
+ * Default customization values for viewport scrollbar behavior.
9088
+ * The `progress` scrollbar variant is in full mode for stack viewports and
9089
+ * acquisition-plane orthographic viewports.
9090
+ * Otherwise, viewports using the `progress` scrollbar show only the indicator.
9091
+ *
9092
+ * - `viewportScrollbar.variant`: `'progress' | 'legacy'` (default: `'progress'`)
9093
+ * - `viewportScrollbar.showLoadedEndpoints`: show loaded-range endpoint caps in full mode
9094
+ * - `viewportScrollbar.showLoadedFill`: show loaded/cached fill in full mode
9095
+ * - `viewportScrollbar.showViewedFill`: show viewed fill in full mode
9096
+ * - `viewportScrollbar.showLoadingPattern`: show loading pattern in full mode while not fully loaded
9097
+ * - `viewportScrollbar.viewedDwellMs`: delay before marking current image viewed in full mode (ms)
9098
+ * - `viewportScrollbar.loadedBatchIntervalMs`: loaded-state version batch interval in full mode (ms)
9099
+ * - `viewportScrollbar.indicator`: optional custom indicator config
9100
+ */
9101
+ function getViewportScrollbarCustomization() {
9102
+ return {
9103
+ 'viewportScrollbar.variant': 'progress',
9104
+ 'viewportScrollbar.showLoadedEndpoints': true,
9105
+ 'viewportScrollbar.showLoadedFill': true,
9106
+ 'viewportScrollbar.showViewedFill': true,
9107
+ 'viewportScrollbar.showLoadingPattern': true,
9108
+ 'viewportScrollbar.viewedDwellMs': 0,
9109
+ 'viewportScrollbar.loadedBatchIntervalMs': 200,
9110
+ 'viewportScrollbar.indicator': {}
9111
+ };
9112
+ }
9160
9113
  ;// ../../../extensions/cornerstone/src/getCustomizationModule.tsx
9161
9114
 
9162
9115
 
@@ -9171,6 +9124,7 @@ function ViewportDownloadFormNew({
9171
9124
 
9172
9125
 
9173
9126
 
9127
+
9174
9128
  function getCustomizationModule({
9175
9129
  commandsManager,
9176
9130
  servicesManager,
@@ -9195,7 +9149,8 @@ function getCustomizationModule({
9195
9149
  ...windowLevelPresetsCustomization,
9196
9150
  ...miscCustomization,
9197
9151
  ...captureViewportModalCustomization,
9198
- ...viewportDownloadWarningCustomization
9152
+ ...viewportDownloadWarningCustomization,
9153
+ ...getViewportScrollbarCustomization()
9199
9154
  }
9200
9155
  }];
9201
9156
  }
@@ -9563,17 +9518,39 @@ const CornerstoneViewportDownloadForm = ({
9563
9518
  } = activeViewportEnabledElement;
9564
9519
  const downloadViewport = renderingEngine.getViewport(VIEWPORT_ID);
9565
9520
  try {
9521
+ // Capture current viewport state
9522
+ // - properties: VOI, colormap, interpolation, etc.
9523
+ // - viewPresentation: flip/rotate/zoom presentation state added for
9524
+ // saving flip and rotation for capture
9525
+ // - viewReference: image/volume reference
9526
+ const properties = viewport.getProperties();
9527
+ const viewPresentation = viewport.getViewPresentation?.();
9528
+ const viewRef = viewport.getViewReference?.();
9566
9529
  if (downloadViewport instanceof esm.StackViewport) {
9567
9530
  const imageId = viewport.getCurrentImageId();
9568
- const properties = viewport.getProperties();
9569
9531
  await downloadViewport.setStack([imageId]);
9570
- downloadViewport.setProperties(properties);
9571
9532
  } else if (downloadViewport instanceof esm.BaseVolumeViewport) {
9572
9533
  const volumeIds = viewport.getAllVolumeIds();
9573
- downloadViewport.setVolumes([{
9534
+ await downloadViewport.setVolumes([{
9574
9535
  volumeId: volumeIds[0]
9575
9536
  }]);
9576
9537
  }
9538
+
9539
+ // Apply presentation state so captured image preserves flip/rotate
9540
+ if (viewPresentation && downloadViewport.setViewPresentation) {
9541
+ downloadViewport.setViewPresentation(viewPresentation);
9542
+ }
9543
+
9544
+ // Apply viewport display properties
9545
+ downloadViewport.setProperties(properties);
9546
+
9547
+ // Ensure correct image/volume reference
9548
+ if (viewRef && downloadViewport.setViewReference) {
9549
+ downloadViewport.setViewReference(viewRef);
9550
+ }
9551
+ downloadViewport.render();
9552
+
9553
+ // Re-apply segmentation overlays to the download viewport
9577
9554
  if (segmentationRepresentations?.length) {
9578
9555
  segmentationRepresentations.forEach(segRepresentation => {
9579
9556
  const {
@@ -9667,6 +9644,36 @@ const CornerstoneViewportDownloadForm = ({
9667
9644
  filename
9668
9645
  });
9669
9646
  };
9647
+ const handleCopyToClipboard = async () => {
9648
+ const divForDownloadViewport = document.querySelector(`div[data-viewport-uid="${VIEWPORT_ID}"]`);
9649
+ if (!divForDownloadViewport) {
9650
+ console.debug('No viewport found for copy');
9651
+ return;
9652
+ }
9653
+ try {
9654
+ const canvas = await (0,html2canvas_esm/* default */.A)(divForDownloadViewport);
9655
+
9656
+ // Clipboard API only supports PNG format in most browsers
9657
+ const blob = await new Promise((resolve, reject) => {
9658
+ canvas.toBlob(blob => {
9659
+ if (blob) {
9660
+ resolve(blob);
9661
+ } else {
9662
+ reject(new Error('Failed to create blob from canvas'));
9663
+ }
9664
+ }, 'image/png', 1.0);
9665
+ });
9666
+
9667
+ // Copy to clipboard using the Clipboard API
9668
+ await navigator.clipboard.write([new ClipboardItem({
9669
+ 'image/png': blob
9670
+ })]);
9671
+ console.log('Image copied to clipboard successfully');
9672
+ } catch (error) {
9673
+ console.error('Failed to copy image to clipboard:', error);
9674
+ throw error;
9675
+ }
9676
+ };
9670
9677
  const ViewportDownloadFormNew = customizationService.getCustomization('ohif.captureViewportModal');
9671
9678
  return /*#__PURE__*/react.createElement(ViewportDownloadFormNew, {
9672
9679
  onClose: hide,
@@ -9680,6 +9687,7 @@ const CornerstoneViewportDownloadForm = ({
9680
9687
  onEnableViewport: handleEnableViewport,
9681
9688
  onDisableViewport: handleDisableViewport,
9682
9689
  onDownload: handleDownload,
9690
+ onCopyToClipboard: handleCopyToClipboard,
9683
9691
  warningState: warningState
9684
9692
  });
9685
9693
  };
@@ -10756,11 +10764,26 @@ function commandsModule({
10756
10764
  segmentIndex: targetIndex
10757
10765
  } = targetSegmentation;
10758
10766
 
10767
+ // Check if the segment has voxels before computing bidirectional measurement
10768
+ const uniqueSegmentIndices = dist_esm.utilities.segmentation.getUniqueSegmentIndices(targetId);
10769
+ const hasVoxels = uniqueSegmentIndices.includes(targetIndex);
10770
+ if (!hasVoxels) {
10771
+ uiNotificationService.show({
10772
+ title: i18n_src/* default */.A.t('SegmentationPanel:Segment Bidirectional'),
10773
+ message: i18n_src/* default */.A.t('SegmentationPanel:Draw a segment before using bidirectional measurement'),
10774
+ type: 'warning'
10775
+ });
10776
+ return;
10777
+ }
10778
+
10759
10779
  // Get bidirectional measurement data
10760
10780
  const bidirectionalData = await dist_esm.utilities.segmentation.getSegmentLargestBidirectional({
10761
10781
  segmentationId: targetId,
10762
10782
  segmentIndices: [targetIndex]
10763
10783
  });
10784
+ if (!bidirectionalData.length) {
10785
+ return;
10786
+ }
10764
10787
  const activeViewportId = viewportGridService.getActiveViewportId();
10765
10788
 
10766
10789
  // Process each bidirectional measurement
@@ -10799,7 +10822,7 @@ function commandsModule({
10799
10822
  // get the active segmentIndex bidirectional annotation and jump to it
10800
10823
  const activeBidirectional = bidirectionalData.find(measurement => measurement.segmentIndex === targetIndex);
10801
10824
  commandsManager.run('jumpToMeasurement', {
10802
- uid: activeBidirectional.annotationUID
10825
+ uid: activeBidirectional?.annotationUID
10803
10826
  });
10804
10827
  },
10805
10828
  interpolateLabelmap: () => {
@@ -10962,7 +10985,7 @@ function commandsModule({
10962
10985
  return;
10963
10986
  }
10964
10987
  if (!labelConfig) {
10965
- const label = await (0,default_src.callInputDialog)({
10988
+ const label = await (0,default_src/* callInputDialog */.l5)({
10966
10989
  uiDialogService,
10967
10990
  title: i18n_src/* default */.A.t('Tools:Edit Measurement Label'),
10968
10991
  placeholder: measurement.label || i18n_src/* default */.A.t('Tools:Enter new label'),
@@ -10976,7 +10999,7 @@ function commandsModule({
10976
10999
  }
10977
11000
  return;
10978
11001
  }
10979
- const val = await (0,default_src.callInputDialogAutoComplete)({
11002
+ const val = await (0,default_src/* callInputDialogAutoComplete */.fq)({
10980
11003
  measurement,
10981
11004
  uiDialogService,
10982
11005
  labelConfig,
@@ -11099,6 +11122,9 @@ function commandsModule({
11099
11122
  uid,
11100
11123
  displayMeasurements = []
11101
11124
  }) => {
11125
+ if (!uid) {
11126
+ return;
11127
+ }
11102
11128
  measurementService.jumpToMeasurement(viewportGridService.getActiveViewportId(), uid);
11103
11129
  for (const measurement of displayMeasurements) {
11104
11130
  measurement.isActive = measurement.uid === uid;
@@ -11196,7 +11222,7 @@ function commandsModule({
11196
11222
  const labelConfig = customizationService.getCustomization('measurementLabels');
11197
11223
  const renderContent = customizationService.getCustomization('ui.labellingComponent');
11198
11224
  if (!labelConfig) {
11199
- const label = await (0,default_src.callInputDialog)({
11225
+ const label = await (0,default_src/* callInputDialog */.l5)({
11200
11226
  uiDialogService,
11201
11227
  title: i18n_src/* default */.A.t('Tools:Edit Arrow Text'),
11202
11228
  placeholder: data?.data?.label || i18n_src/* default */.A.t('Tools:Enter new text'),
@@ -11205,7 +11231,7 @@ function commandsModule({
11205
11231
  callback?.(label);
11206
11232
  return;
11207
11233
  }
11208
- const value = await (0,default_src.callInputDialogAutoComplete)({
11234
+ const value = await (0,default_src/* callInputDialogAutoComplete */.fq)({
11209
11235
  uiDialogService,
11210
11236
  labelConfig,
11211
11237
  renderContent
@@ -12101,7 +12127,7 @@ function commandsModule({
12101
12127
  segmentationService,
12102
12128
  viewportGridService
12103
12129
  } = servicesManager.services;
12104
- const displaySetInstanceUIDs = await (0,default_src.createReportAsync)({
12130
+ const displaySetInstanceUIDs = await (0,default_src/* createReportAsync */.Vy)({
12105
12131
  servicesManager,
12106
12132
  getReport: () => commandsManager.runCommand('storeSegmentation', args),
12107
12133
  reportType: 'Segmentation'
@@ -12178,14 +12204,15 @@ function commandsModule({
12178
12204
  * @param props.segmentationId - The ID of the segmentation to remove
12179
12205
  */
12180
12206
  removeSegmentationFromViewportCommand: ({
12181
- segmentationId
12207
+ segmentationId: displaySetInstanceUID
12182
12208
  }) => {
12183
12209
  const {
12184
- segmentationService,
12185
12210
  viewportGridService
12186
12211
  } = servicesManager.services;
12187
- segmentationService.removeSegmentationRepresentations(viewportGridService.getActiveViewportId(), {
12188
- segmentationId
12212
+ const viewportId = viewportGridService.getActiveViewportId();
12213
+ commandsManager.runCommand('removeDisplaySetLayer', {
12214
+ viewportId,
12215
+ displaySetInstanceUID
12189
12216
  });
12190
12217
  },
12191
12218
  /**
@@ -12213,7 +12240,7 @@ function commandsModule({
12213
12240
  return;
12214
12241
  }
12215
12242
  const segment = segmentation.segments[segmentIndex];
12216
- (0,default_src.callInputDialog)({
12243
+ (0,default_src/* callInputDialog */.l5)({
12217
12244
  uiDialogService,
12218
12245
  title: i18n_src/* default */.A.t('Tools:Edit Segment Label'),
12219
12246
  placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
@@ -12236,7 +12263,7 @@ function commandsModule({
12236
12263
  const {
12237
12264
  label
12238
12265
  } = segmentation;
12239
- (0,default_src.callInputDialog)({
12266
+ (0,default_src/* callInputDialog */.l5)({
12240
12267
  uiDialogService,
12241
12268
  title: i18n_src/* default */.A.t('Tools:Edit Segmentation Label'),
12242
12269
  placeholder: i18n_src/* default */.A.t('Tools:Enter new label'),
@@ -12266,7 +12293,7 @@ function commandsModule({
12266
12293
  a: color[3] / 255.0
12267
12294
  };
12268
12295
  uiDialogService.show({
12269
- content: default_src.colorPickerDialog,
12296
+ content: default_src/* colorPickerDialog */.wS,
12270
12297
  title: i18n_src/* default */.A.t('Tools:Segment Color'),
12271
12298
  contentProps: {
12272
12299
  value: rgbaColor,
@@ -13256,6 +13283,29 @@ const HYDRATE_SEG_SYNC_GROUP = {
13256
13283
  matchingRules: ['sameFOR']
13257
13284
  }
13258
13285
  };
13286
+ const viewportStructure = {
13287
+ layoutType: 'grid',
13288
+ properties: {
13289
+ rows: 1,
13290
+ columns: 3,
13291
+ layoutOptions: [{
13292
+ x: 0,
13293
+ y: 0,
13294
+ width: 1 / 3,
13295
+ height: 1
13296
+ }, {
13297
+ x: 1 / 3,
13298
+ y: 0,
13299
+ width: 1 / 3,
13300
+ height: 1
13301
+ }, {
13302
+ x: 2 / 3,
13303
+ y: 0,
13304
+ width: 1 / 3,
13305
+ height: 1
13306
+ }]
13307
+ }
13308
+ };
13259
13309
  const mpr = {
13260
13310
  id: 'mpr',
13261
13311
  name: i18next/* default */.A.t('Hps:MPR'),
@@ -13286,29 +13336,7 @@ const mpr = {
13286
13336
  },
13287
13337
  stages: [{
13288
13338
  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
- },
13339
+ viewportStructure,
13312
13340
  viewports: [{
13313
13341
  viewportOptions: {
13314
13342
  viewportId: 'mpr-axial',
@@ -13352,6 +13380,52 @@ const mpr = {
13352
13380
  id: 'activeDisplaySet'
13353
13381
  }]
13354
13382
  }]
13383
+ }, {
13384
+ name: 'MPR Reformat 1x3',
13385
+ viewportStructure,
13386
+ viewports: [{
13387
+ viewportOptions: {
13388
+ viewportId: 'mpr-axial',
13389
+ toolGroupId: 'mpr',
13390
+ viewportType: 'volume',
13391
+ orientation: 'axial_reformat',
13392
+ initialImageOptions: {
13393
+ preset: 'middle'
13394
+ },
13395
+ syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
13396
+ },
13397
+ displaySets: [{
13398
+ id: 'activeDisplaySet'
13399
+ }]
13400
+ }, {
13401
+ viewportOptions: {
13402
+ viewportId: 'mpr-sagittal',
13403
+ toolGroupId: 'mpr',
13404
+ viewportType: 'volume',
13405
+ orientation: 'sagittal_reformat',
13406
+ initialImageOptions: {
13407
+ preset: 'middle'
13408
+ },
13409
+ syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
13410
+ },
13411
+ displaySets: [{
13412
+ id: 'activeDisplaySet'
13413
+ }]
13414
+ }, {
13415
+ viewportOptions: {
13416
+ viewportId: 'mpr-coronal',
13417
+ toolGroupId: 'mpr',
13418
+ viewportType: 'volume',
13419
+ orientation: 'coronal_reformat',
13420
+ initialImageOptions: {
13421
+ preset: 'middle'
13422
+ },
13423
+ syncGroups: [VOI_SYNC_GROUP, HYDRATE_SEG_SYNC_GROUP]
13424
+ },
13425
+ displaySets: [{
13426
+ id: 'activeDisplaySet'
13427
+ }]
13428
+ }]
13355
13429
  }]
13356
13430
  };
13357
13431
  ;// ../../../extensions/cornerstone/src/hps/fourUp.ts
@@ -15342,6 +15416,9 @@ function ViewportDataOverlayMenu({
15342
15416
  } = (0,useViewportDisplaySets/* useViewportDisplaySets */.N)(viewportId);
15343
15417
  const [optimisticOverlayDisplaySets, setOptimisticOverlayDisplaySets] = (0,react.useState)(overlayDisplaySets);
15344
15418
  const [thresholdOpacityEnabled, setThresholdOpacityEnabled] = (0,react.useState)(false);
15419
+ (0,react.useEffect)(() => {
15420
+ setOptimisticOverlayDisplaySets(overlayDisplaySets);
15421
+ }, [backgroundDisplaySet?.displaySetInstanceUID, overlayDisplaySets]);
15345
15422
 
15346
15423
  /**
15347
15424
  * Change the background display set
@@ -15648,7 +15725,8 @@ function ViewportDataOverlayMenu({
15648
15725
  }
15649
15726
  }
15650
15727
  }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
15651
- className: "flex-1"
15728
+ className: "flex-1",
15729
+ "data-cy": `overlay-background-ds-select-${viewportId}`
15652
15730
  }, /*#__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
15731
  key: displaySet.displaySetInstanceUID,
15654
15732
  value: displaySet.displaySetInstanceUID,
@@ -15923,7 +16001,7 @@ function ViewportOrientationMenu({
15923
16001
  }) : null), /*#__PURE__*/react.createElement("div", {
15924
16002
  className: "flex-1 text-left"
15925
16003
  }, "Acquisition")), /*#__PURE__*/react.createElement("div", {
15926
- className: "mx-1 my-2 border-t border-white/20"
16004
+ className: "border-input mx-1 my-2 border-t"
15927
16005
  }), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
15928
16006
  variant: "ghost",
15929
16007
  className: "flex h-7 w-full flex-shrink-0 items-center justify-start self-stretch px-1 py-0",
@@ -16264,7 +16342,7 @@ function VolumeRenderingPresetsContent({
16264
16342
  }
16265
16343
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.ByName, {
16266
16344
  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'
16345
+ 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
16346
  }), /*#__PURE__*/react.createElement("label", {
16269
16347
  className: "text-muted-foreground mt-1 text-left text-xs"
16270
16348
  }, formatLabel(preset.name, 11)))))), /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu, {
@@ -17410,9 +17488,9 @@ function ModalityLoadBadge({
17410
17488
  if (!statusInfo.isHydrated) {
17411
17489
  return /*#__PURE__*/react.createElement("div", {
17412
17490
  "data-cy": `ModalityLoadBadge-${viewportId}`,
17413
- className: "flex h-6 cursor-default text-sm leading-6 text-white"
17491
+ className: "text-foreground flex h-6 cursor-default text-sm leading-6"
17414
17492
  }, /*#__PURE__*/react.createElement("div", {
17415
- className: "bg-customgray-100 flex min-w-[45px] items-center rounded-l-xl rounded-r p-1"
17493
+ className: "bg-popover flex min-w-[45px] items-center rounded-l-xl rounded-r p-1"
17416
17494
  }, /*#__PURE__*/react.createElement(StatusIcon, null), /*#__PURE__*/react.createElement("span", {
17417
17495
  className: "ml-1"
17418
17496
  }, statusInfo.type)), statusInfo.type !== 'SR' && /*#__PURE__*/react.createElement(ui_next_src/* ViewportActionButton */.N8H, {
@@ -18829,7 +18907,12 @@ const segmentationRepresentationModifiedCallback = async (synchronizerInstance,
18829
18907
  const sourceDisplaySetUIDs = extractDisplaySetUIDs(sourceViewportInfo);
18830
18908
  const targetDisplaySetUIDs = extractDisplaySetUIDs(targetViewportInfo);
18831
18909
  const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs);
18832
- if (!sharedDisplaySetExists && !viewport.getFrameOfReferenceUID()) {
18910
+ const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID();
18911
+ const sourceFrameOfReferenceUID = (0,esm.getEnabledElementByViewportId)(sourceViewportId)?.viewport?.getFrameOfReferenceUID();
18912
+ if (!sharedDisplaySetExists && !targetFrameOfReferenceUID) {
18913
+ return;
18914
+ }
18915
+ if (!sharedDisplaySetExists && targetFrameOfReferenceUID !== sourceFrameOfReferenceUID) {
18833
18916
  return;
18834
18917
  }
18835
18918
  const targetViewportRepresentation = segmentationService.getSegmentationRepresentations(targetViewportId, {
@@ -19196,11 +19279,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
19196
19279
  this.EVENTS = SegmentationService_EVENTS;
19197
19280
  this.destroy = () => {
19198
19281
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
19199
- esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationModifiedFromSource);
19282
+ esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
19200
19283
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
19201
19284
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
19202
19285
  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);
19286
+ esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
19204
19287
  esm.eventTarget.removeEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
19205
19288
  this.reset();
19206
19289
  };
@@ -19261,6 +19344,16 @@ class SegmentationService extends src/* PubSubService */.Rc {
19261
19344
  viewportId
19262
19345
  });
19263
19346
  };
19347
+ this._onSegmentationRepresentationRemovedFromSource = evt => {
19348
+ const {
19349
+ segmentationId,
19350
+ viewportId
19351
+ } = evt.detail;
19352
+ this._broadcastEvent(this.EVENTS.SEGMENTATION_REPRESENTATION_REMOVED, {
19353
+ segmentationId,
19354
+ viewportId
19355
+ });
19356
+ };
19264
19357
  this._onSegmentationModifiedFromSource = evt => {
19265
19358
  const {
19266
19359
  segmentationId
@@ -19277,6 +19370,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
19277
19370
  segmentationId
19278
19371
  });
19279
19372
  };
19373
+ this._onSegmentationRemovedFromSource = evt => {
19374
+ const {
19375
+ segmentationId
19376
+ } = evt.detail;
19377
+ this._broadcastEvent(this.EVENTS.SEGMENTATION_REMOVED, {
19378
+ segmentationId
19379
+ });
19380
+ };
19280
19381
  this._onAnnotationCutMergeProcessCompletedFromSource = evt => {
19281
19382
  const {
19282
19383
  segmentationId
@@ -19482,6 +19583,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19482
19583
  },
19483
19584
  config: {
19484
19585
  label,
19586
+ fallbackLabel: `S:${displaySet.SeriesNumber} ${displaySet.Modality}`,
19485
19587
  segments: options?.segments && Object.keys(options.segments).length > 0 ? options.segments : {
19486
19588
  1: {
19487
19589
  label: `${i18n_src/* default */.A.t('Segment')} 1`,
@@ -19613,6 +19715,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19613
19715
  },
19614
19716
  config: {
19615
19717
  label: segDisplaySet.SeriesDescription,
19718
+ fallbackLabel: `S:${segDisplaySet.SeriesNumber} ${segDisplaySet.Modality}`,
19616
19719
  segments
19617
19720
  }
19618
19721
  };
@@ -19673,7 +19776,8 @@ class SegmentationService extends src/* PubSubService */.Rc {
19673
19776
  }
19674
19777
  },
19675
19778
  config: {
19676
- label: rtDisplaySet.SeriesDescription
19779
+ label: rtDisplaySet.SeriesDescription,
19780
+ fallbackLabel: `S:${rtDisplaySet.SeriesNumber} ${rtDisplaySet.Modality}`
19677
19781
  }
19678
19782
  };
19679
19783
  const segments = {};
@@ -20170,14 +20274,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
20170
20274
  }
20171
20275
  /**
20172
20276
  * Clears segmentation representations from the viewport.
20173
- * Unlike removeSegmentationRepresentations, this doesn't update
20277
+ * Unlike removeRepresentationsFromViewport, this doesn't update
20174
20278
  * removed display set and representation maps.
20175
20279
  * We track removed segmentations manually to avoid re-adding them
20176
20280
  * when the display set is added again.
20177
20281
  * @param viewportId - The viewport ID to clear segmentation representations from.
20178
20282
  */
20179
20283
  clearSegmentationRepresentations(viewportId) {
20180
- this.removeSegmentationRepresentations(viewportId);
20284
+ this.removeRepresentationsFromViewport(viewportId);
20181
20285
  }
20182
20286
 
20183
20287
  /**
@@ -20192,7 +20296,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20192
20296
  }
20193
20297
 
20194
20298
  /**
20195
- * It removes the segmentation representations from the viewport.
20299
+ * Removes segmentation representations from the viewport.
20196
20300
  * @param viewportId - The viewport id to remove the segmentation representations from.
20197
20301
  * @param specifier - The specifier to remove the segmentation representations.
20198
20302
  *
@@ -20202,7 +20306,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20202
20306
  * If a type specifier is provided, only the segmentation representation with the specified type are removed.
20203
20307
  * If both a segmentationId and type specifier are provided, only the segmentation representation with the specified segmentationId and type are removed.
20204
20308
  */
20205
- removeSegmentationRepresentations(viewportId, specifier = {}) {
20309
+ removeRepresentationsFromViewport(viewportId, specifier = {}) {
20206
20310
  dist_esm.segmentation.removeSegmentationRepresentations(viewportId, specifier);
20207
20311
  }
20208
20312
 
@@ -20558,6 +20662,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
20558
20662
  id: id,
20559
20663
  segmentationId,
20560
20664
  label: segmentation.label,
20665
+ fallbackLabel: segmentation.fallbackLabel,
20561
20666
  active,
20562
20667
  type,
20563
20668
  visible,
@@ -20570,11 +20675,11 @@ class SegmentationService extends src/* PubSubService */.Rc {
20570
20675
  }
20571
20676
  _initSegmentationService() {
20572
20677
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_MODIFIED, this._onSegmentationModifiedFromSource);
20573
- esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationModifiedFromSource);
20678
+ esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REMOVED, this._onSegmentationRemovedFromSource);
20574
20679
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_DATA_MODIFIED, this._onSegmentationDataModifiedFromSource);
20575
20680
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_MODIFIED, this._onSegmentationRepresentationModifiedFromSource);
20576
20681
  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);
20682
+ esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationRemovedFromSource);
20578
20683
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
20579
20684
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, this._onAnnotationCutMergeProcessCompletedFromSource);
20580
20685
  }
@@ -20780,6 +20885,7 @@ const ORTHOGRAPHIC = 'orthographic';
20780
20885
  const VOLUME_3D = 'volume3d';
20781
20886
  const VIDEO = 'video';
20782
20887
  const WHOLESLIDE = 'wholeslide';
20888
+ const ECG = 'ecg';
20783
20889
  function getCornerstoneViewportType(viewportType, displaySets) {
20784
20890
  const lowerViewportType = displaySets?.[0]?.viewportType?.toLowerCase() || viewportType.toLowerCase();
20785
20891
  if (lowerViewportType === STACK) {
@@ -20791,13 +20897,16 @@ function getCornerstoneViewportType(viewportType, displaySets) {
20791
20897
  if (lowerViewportType === WHOLESLIDE) {
20792
20898
  return esm.Enums.ViewportType.WHOLE_SLIDE;
20793
20899
  }
20900
+ if (lowerViewportType === ECG) {
20901
+ return esm.Enums.ViewportType.ECG;
20902
+ }
20794
20903
  if (lowerViewportType === VOLUME || lowerViewportType === ORTHOGRAPHIC) {
20795
20904
  return esm.Enums.ViewportType.ORTHOGRAPHIC;
20796
20905
  }
20797
20906
  if (lowerViewportType === VOLUME_3D) {
20798
20907
  return esm.Enums.ViewportType.VOLUME_3D;
20799
20908
  }
20800
- throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide`);
20909
+ throw new Error(`Invalid viewport type: ${viewportType}. Valid types are: stack, volume, video, wholeslide, ecg`);
20801
20910
  }
20802
20911
  ;// ../../../extensions/cornerstone/src/services/CornerstoneCacheService/CornerstoneCacheService.ts
20803
20912
  var _CornerstoneCacheService;
@@ -21104,15 +21213,24 @@ function getCornerstoneBlendMode(blendMode) {
21104
21213
  const AXIAL = 'axial';
21105
21214
  const SAGITTAL = 'sagittal';
21106
21215
  const CORONAL = 'coronal';
21216
+ const AXIAL_REFORMAT = 'axial_reformat';
21217
+ const SAGITTAL_REFORMAT = 'sagittal_reformat';
21218
+ const CORONAL_REFORMAT = 'coronal_reformat';
21107
21219
  function getCornerstoneOrientation(orientation) {
21108
21220
  if (orientation) {
21109
21221
  switch (orientation.toLowerCase()) {
21110
21222
  case AXIAL:
21111
21223
  return esm.Enums.OrientationAxis.AXIAL;
21224
+ case AXIAL_REFORMAT:
21225
+ return esm.Enums.OrientationAxis.AXIAL_REFORMAT;
21112
21226
  case SAGITTAL:
21113
21227
  return esm.Enums.OrientationAxis.SAGITTAL;
21228
+ case SAGITTAL_REFORMAT:
21229
+ return esm.Enums.OrientationAxis.SAGITTAL_REFORMAT;
21114
21230
  case CORONAL:
21115
21231
  return esm.Enums.OrientationAxis.CORONAL;
21232
+ case CORONAL_REFORMAT:
21233
+ return esm.Enums.OrientationAxis.CORONAL_REFORMAT;
21116
21234
  default:
21117
21235
  return esm.Enums.OrientationAxis.ACQUISITION;
21118
21236
  }
@@ -22072,6 +22190,15 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22072
22190
  /**
22073
22191
  * Sets the image data for the given viewport.
22074
22192
  */
22193
+ async _setEcgViewport(viewport, viewportData) {
22194
+ const [displaySet] = viewportData.data;
22195
+ const imageId = displaySet.imageIds?.[0];
22196
+ if (!imageId) {
22197
+ console.error('[CornerstoneViewportService] ECG display set has no imageId');
22198
+ return;
22199
+ }
22200
+ return viewport.setEcg(imageId);
22201
+ }
22075
22202
  async _setOtherViewport(viewport, viewportData, viewportInfo, _presentations = {}) {
22076
22203
  const [displaySet] = viewportData.data;
22077
22204
  return viewport.setDataIds(displaySet.imageIds, {
@@ -22140,32 +22267,25 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22140
22267
  if (initialImageIndexToUse === undefined || initialImageIndexToUse === null || initialImageIndexToUse < 0) {
22141
22268
  initialImageIndexToUse = this._getInitialImageIndexForViewport(viewportInfo, imageIds) || 0;
22142
22269
  }
22143
- return viewport.setStack(imageIds, initialImageIndexToUse).then(() => {
22270
+ await viewport.setStack(imageIds, initialImageIndexToUse);
22271
+ viewport.setProperties({
22272
+ ...properties
22273
+ });
22274
+ this.setPresentations(viewport.id, presentations, viewportInfo);
22275
+ await this._addOverlayRepresentations(overlayProcessingResults);
22276
+ if (displayArea) {
22277
+ viewport.setDisplayArea(displayArea);
22278
+ }
22279
+ if (rotation) {
22144
22280
  viewport.setProperties({
22145
- ...properties
22281
+ rotation
22146
22282
  });
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
- });
22283
+ }
22284
+ if (flipHorizontal) {
22285
+ viewport.setCamera({
22286
+ flipHorizontal: true
22287
+ });
22288
+ }
22169
22289
  }
22170
22290
  _getInitialImageIndexForViewport(viewportInfo, imageIds) {
22171
22291
  const initialImageOptions = viewportInfo.getInitialImageOptions();
@@ -22389,15 +22509,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22389
22509
  });
22390
22510
  }
22391
22511
  await viewport.setVolumes(volumeInputArray);
22392
- if (overlayProcessingResults?.length) {
22393
- overlayProcessingResults.forEach(({
22394
- addOverlayFn
22395
- }) => {
22396
- if (addOverlayFn) {
22397
- addOverlayFn();
22398
- }
22399
- });
22400
- }
22512
+ await this._addOverlayRepresentations(overlayProcessingResults);
22401
22513
  viewport.render();
22402
22514
  volumesProperties.forEach(({
22403
22515
  properties,
@@ -22460,7 +22572,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22460
22572
  const {
22461
22573
  predecessorImageId
22462
22574
  } = displaySet;
22463
- segmentationService.addSegmentationRepresentation(viewport.id, {
22575
+ const segmentationRepresentationPromise = segmentationService.addSegmentationRepresentation(viewport.id, {
22464
22576
  segmentationId,
22465
22577
  predecessorImageId,
22466
22578
  type: representationType,
@@ -22468,11 +22580,21 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22468
22580
  blendMode: viewport?.getBlendMode?.() === 1 ? dist_esm_enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
22469
22581
  }
22470
22582
  });
22471
-
22472
22583
  // store the segmentation presentation id in the viewport info
22473
22584
  this.storePresentation({
22474
22585
  viewportId: viewport.id
22475
22586
  });
22587
+ return segmentationRepresentationPromise;
22588
+ }
22589
+ async _addOverlayRepresentations(overlayProcessingResults) {
22590
+ if (!overlayProcessingResults?.length) {
22591
+ return;
22592
+ }
22593
+ for (const overlayProcessingResult of overlayProcessingResults) {
22594
+ if (overlayProcessingResult?.addOverlayFn) {
22595
+ await overlayProcessingResult.addOverlayFn();
22596
+ }
22597
+ }
22476
22598
  }
22477
22599
 
22478
22600
  // Todo: keepCamera is an interim solution until we have a better solution for
@@ -22507,6 +22629,9 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22507
22629
  if ([esm.VolumeViewport, esm.VolumeViewport3D].some(type => viewport instanceof type)) {
22508
22630
  return this._setVolumeViewport(viewport, viewportData, viewportInfo, presentations);
22509
22631
  }
22632
+ if (viewport instanceof esm.ECGViewport) {
22633
+ return this._setEcgViewport(viewport, viewportData);
22634
+ }
22510
22635
  return this._setOtherViewport(viewport, viewportData, viewportInfo, presentations);
22511
22636
  }
22512
22637
 
@@ -22549,8 +22674,8 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22549
22674
  if (!displaySet) {
22550
22675
  return;
22551
22676
  }
22552
- if (displaySet.frameOfReferenceUID) {
22553
- return displaySet.frameOfReferenceUID;
22677
+ if (displaySet.FrameOfReferenceUID) {
22678
+ return displaySet.FrameOfReferenceUID;
22554
22679
  }
22555
22680
  if (displaySet.Modality === 'SEG') {
22556
22681
  const {
@@ -22728,6 +22853,8 @@ CornerstoneViewportService.REGISTRATION = {
22728
22853
  }
22729
22854
  };
22730
22855
  /* harmony default export */ const ViewportService_CornerstoneViewportService = (CornerstoneViewportService);
22856
+ // EXTERNAL MODULE: ../../../extensions/cornerstone/src/utils/getDataIdForViewport.ts
22857
+ var getDataIdForViewport = __webpack_require__(67142);
22731
22858
  ;// ../../../extensions/cornerstone/src/types/Colorbar.ts
22732
22859
  // Position options
22733
22860
 
@@ -22770,6 +22897,7 @@ var _ColorbarService;
22770
22897
 
22771
22898
 
22772
22899
 
22900
+
22773
22901
  class ColorbarService extends src/* PubSubService */.Rc {
22774
22902
  constructor(servicesManager) {
22775
22903
  super(ColorbarService.EVENTS);
@@ -22793,23 +22921,6 @@ class ColorbarService extends src/* PubSubService */.Rc {
22793
22921
  this.servicesManager = servicesManager;
22794
22922
  }
22795
22923
 
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
22924
  /**
22814
22925
  * Adds a colorbar to a specific viewport identified by `viewportId`, using the provided `displaySetInstanceUIDs` and `options`.
22815
22926
  * This method prepares the colorbar state that will be used by the ViewportColorbarsContainer component.
@@ -22841,7 +22952,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
22841
22952
  if (displaySet.isOverlayDisplaySet) {
22842
22953
  return;
22843
22954
  }
22844
- const dataId = this.getDataIdForViewport(viewport, displaySetInstanceUID);
22955
+ const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
22845
22956
  const properties = dataId ? viewport.getProperties(dataId) : viewport.getProperties();
22846
22957
  const colormap = properties?.colormap;
22847
22958
  if (activeColormapName && !colormap) {
@@ -22979,7 +23090,7 @@ class ColorbarService extends src/* PubSubService */.Rc {
22979
23090
  }
22980
23091
 
22981
23092
  // Get the appropriate dataId for this viewport/displaySet combination
22982
- const dataId = this.getDataIdForViewport(viewport, displaySetInstanceUID);
23093
+ const dataId = (0,getDataIdForViewport/* getDataIdForViewport */.V)(viewport, displaySetInstanceUID);
22983
23094
 
22984
23095
  // Set properties with or without dataId based on what the viewport supports
22985
23096
  viewport.setProperties({
@@ -23005,6 +23116,54 @@ ColorbarService.REGISTRATION = {
23005
23116
  ;// ../../../extensions/cornerstone/src/services/ColorbarService/index.ts
23006
23117
 
23007
23118
  /* harmony default export */ const services_ColorbarService = (ColorbarService);
23119
+ ;// ../../../extensions/cornerstone/src/services/ViewedDataService/ViewedDataService.ts
23120
+ var _ViewedDataService;
23121
+
23122
+ class ViewedDataService extends src/* PubSubService */.Rc {
23123
+ constructor() {
23124
+ super(ViewedDataService.EVENTS);
23125
+ this.viewedDataIds = new Set();
23126
+ }
23127
+ markDataViewed(dataId) {
23128
+ if (!dataId || this.viewedDataIds.has(dataId)) {
23129
+ return;
23130
+ }
23131
+ this.viewedDataIds.add(dataId);
23132
+ this._broadcastEvent(this.EVENTS.VIEWED_DATA_CHANGED, {
23133
+ viewedDataId: dataId
23134
+ });
23135
+ }
23136
+ isDataViewed(dataId) {
23137
+ if (!dataId) {
23138
+ return false;
23139
+ }
23140
+ return this.viewedDataIds.has(dataId);
23141
+ }
23142
+ clearViewedData() {
23143
+ this.viewedDataIds.clear();
23144
+ this._broadcastEvent(this.EVENTS.VIEWED_DATA_CHANGED, {
23145
+ viewedDataCleared: true
23146
+ });
23147
+ }
23148
+ subscribeViewedDataChanges(listener) {
23149
+ return this.subscribe(this.EVENTS.VIEWED_DATA_CHANGED, listener);
23150
+ }
23151
+ }
23152
+ _ViewedDataService = ViewedDataService;
23153
+ ViewedDataService.EVENTS = {
23154
+ VIEWED_DATA_CHANGED: 'event::viewedDataChanged'
23155
+ };
23156
+ ViewedDataService.REGISTRATION = {
23157
+ name: 'viewedDataService',
23158
+ altName: 'ViewedDataService',
23159
+ create: () => {
23160
+ return new _ViewedDataService();
23161
+ }
23162
+ };
23163
+ /* harmony default export */ const ViewedDataService_ViewedDataService = (ViewedDataService);
23164
+ ;// ../../../extensions/cornerstone/src/services/ViewedDataService/index.ts
23165
+
23166
+ /* harmony default export */ const services_ViewedDataService = (ViewedDataService_ViewedDataService);
23008
23167
  ;// ../../../extensions/cornerstone/src/types/Presentation.ts
23009
23168
 
23010
23169
 
@@ -23249,12 +23408,114 @@ const createFrameViewSynchronizer = synchronizerName => {
23249
23408
 
23250
23409
  // EXTERNAL MODULE: ../../../node_modules/dcmjs/build/dcmjs.es.js
23251
23410
  var dcmjs_es = __webpack_require__(5842);
23411
+ ;// ../../../extensions/cornerstone/src/utils/ecgMetadata.ts
23412
+ /**
23413
+ * Decode a multiplexed Int16 buffer into per-channel arrays.
23414
+ * Layout: sample0ch0, sample0ch1 ... sample0chN, sample1ch0, …
23415
+ * Note: DICOM ECG data is canonically SS (signed short). The sampleInterpretation
23416
+ * field is forwarded to ECGViewport for its own use; the raw buffer is always
23417
+ * treated as Int16 because Cornerstone ECGViewport expects Int16Array[].
23418
+ */
23419
+ function decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples) {
23420
+ const src = new Int16Array(buffer);
23421
+ const channels = [];
23422
+ for (let ch = 0; ch < numberOfChannels; ch++) {
23423
+ const out = new Int16Array(numberOfSamples);
23424
+ for (let s = 0; s < numberOfSamples; s++) {
23425
+ out[s] = src[s * numberOfChannels + ch];
23426
+ }
23427
+ channels.push(out);
23428
+ }
23429
+ return channels;
23430
+ }
23431
+
23432
+ /**
23433
+ * Decode a base64 InlineBinary string into a raw ArrayBuffer.
23434
+ */
23435
+ function base64ToArrayBuffer(base64) {
23436
+ const binaryStr = atob(base64);
23437
+ const bytes = new Uint8Array(binaryStr.length);
23438
+ for (let i = 0; i < binaryStr.length; i++) {
23439
+ bytes[i] = binaryStr.charCodeAt(i);
23440
+ }
23441
+ return bytes.buffer;
23442
+ }
23443
+ /**
23444
+ * Parse the naturalized DICOM instance's WaveformSequence and build the ecgModule
23445
+ * that Cornerstone's ECGViewport.setEcg() expects via
23446
+ * metaData.get(MetadataModules.ECG, imageId).
23447
+ *
23448
+ * Returns null if the instance has no WaveformSequence.
23449
+ */
23450
+ function buildEcgModule(instance, userAuthenticationService) {
23451
+ const waveformGroups = instance?.WaveformSequence;
23452
+ if (!waveformGroups?.length) {
23453
+ return null;
23454
+ }
23455
+
23456
+ // Use the first (and typically only) multiplex group
23457
+ const group = waveformGroups[0];
23458
+ const numberOfChannels = group.NumberOfWaveformChannels ?? 0;
23459
+ const numberOfSamples = group.NumberOfWaveformSamples ?? 0;
23460
+ const samplingFrequency = group.SamplingFrequency ?? 1;
23461
+ const bitsAllocated = group.WaveformBitsAllocated ?? 16;
23462
+ const sampleInterpretation = group.WaveformSampleInterpretation ?? 'SS';
23463
+ const multiplexGroupLabel = group.MultiplexGroupLabel ?? '';
23464
+ const channelDefinitionSequence = (group.ChannelDefinitionSequence ?? []).map(ch => ({
23465
+ channelSourceSequence: {
23466
+ codeMeaning: ch?.ChannelSourceSequence?.[0]?.CodeMeaning ?? ch?.ChannelSourceSequence?.[0]?.codeMeaning ?? ''
23467
+ }
23468
+ }));
23469
+ const retrieveBulkData = async () => {
23470
+ const waveformData = group.WaveformData;
23471
+ if (!waveformData) {
23472
+ console.warn('[ECGViewport] No WaveformData found on instance');
23473
+ return [];
23474
+ }
23475
+ let buffer;
23476
+ if (waveformData.InlineBinary) {
23477
+ buffer = base64ToArrayBuffer(waveformData.InlineBinary);
23478
+ } else if (waveformData.BulkDataURI) {
23479
+ const headers = {
23480
+ Accept: 'application/octet-stream'
23481
+ };
23482
+ const authHeader = userAuthenticationService?.getAuthorizationHeader?.();
23483
+ if (authHeader) {
23484
+ Object.assign(headers, authHeader);
23485
+ }
23486
+ const response = await fetch(waveformData.BulkDataURI, {
23487
+ headers
23488
+ });
23489
+ if (!response.ok) {
23490
+ throw new Error(`[ECGViewport] Failed to fetch waveform BulkDataURI: ${response.status}`);
23491
+ }
23492
+ buffer = await response.arrayBuffer();
23493
+ } else {
23494
+ console.warn('[ECGViewport] WaveformData has no InlineBinary or BulkDataURI');
23495
+ return [];
23496
+ }
23497
+ return decodeInt16Multiplex(buffer, numberOfChannels, numberOfSamples);
23498
+ };
23499
+ return {
23500
+ numberOfWaveformChannels: numberOfChannels,
23501
+ numberOfWaveformSamples: numberOfSamples,
23502
+ samplingFrequency,
23503
+ waveformBitsAllocated: bitsAllocated,
23504
+ waveformSampleInterpretation: sampleInterpretation,
23505
+ multiplexGroupLabel,
23506
+ channelDefinitionSequence,
23507
+ waveformData: {
23508
+ retrieveBulkData
23509
+ }
23510
+ };
23511
+ }
23252
23512
  ;// ../../../extensions/cornerstone/src/getSopClassHandlerModule.js
23253
23513
 
23254
23514
 
23255
23515
 
23256
23516
 
23257
23517
 
23518
+
23258
23519
  const {
23259
23520
  MetadataModules
23260
23521
  } = esm.Enums;
@@ -23265,9 +23526,9 @@ const {
23265
23526
  denaturalizeDataset
23266
23527
  } = dcmjs_es/* default.data */.Ay.data.DicomMetaDictionary;
23267
23528
  const {
23268
- transferDenaturalizedDataset,
23269
- fixMultiValueKeys
23270
- } = default_src.dicomWebUtils;
23529
+ /* transferDenaturalizedDataset */ "If": transferDenaturalizedDataset,
23530
+ /* fixMultiValueKeys */ "Uk": fixMultiValueKeys
23531
+ } = default_src/* dicomWebUtils */.CA;
23271
23532
  const SOP_CLASS_UIDS = {
23272
23533
  VL_WHOLE_SLIDE_MICROSCOPY_IMAGE_STORAGE: '1.2.840.10008.5.1.4.1.1.77.1.6'
23273
23534
  };
@@ -23393,8 +23654,92 @@ function getDicomMicroscopySopClassHandler({
23393
23654
  getDisplaySetsFromSeries
23394
23655
  };
23395
23656
  }
23657
+
23658
+ /**
23659
+ * DICOM Waveform SOP Class UIDs for ECG / cardiac electrophysiology.
23660
+ * Reference: https://dicom.nema.org/medical/dicom/current/output/chtml/part04/sect_B.5.html
23661
+ */
23662
+ const ECG_SOP_CLASS_UIDS = {
23663
+ TWELVE_LEAD_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.1',
23664
+ GENERAL_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.2',
23665
+ AMBULATORY_ECG_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.1.3',
23666
+ HEMODYNAMIC_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.2.1',
23667
+ CARDIAC_ELECTROPHYSIOLOGY_WAVEFORM_STORAGE: '1.2.840.10008.5.1.4.1.1.9.3.1'
23668
+ };
23669
+ const ecgSopClassUids = Object.values(ECG_SOP_CLASS_UIDS);
23670
+ const DicomEcgSOPClassHandlerId = '@ohif/extension-cornerstone.sopClassHandlerModule.DicomEcgSopClassHandler';
23671
+ function _getEcgDisplaySetsFromSeries(instances, servicesManager) {
23672
+ const {
23673
+ userAuthenticationService
23674
+ } = servicesManager.services;
23675
+ return instances.map(instance => {
23676
+ const {
23677
+ Modality,
23678
+ SOPInstanceUID
23679
+ } = instance;
23680
+ const {
23681
+ SeriesDescription,
23682
+ SeriesNumber,
23683
+ SeriesDate
23684
+ } = instance;
23685
+ const {
23686
+ SeriesInstanceUID,
23687
+ StudyInstanceUID,
23688
+ SOPClassUID
23689
+ } = instance;
23690
+ const imageId = instance.imageId;
23691
+
23692
+ // Register ECG metadata in the OHIF metadata provider so that
23693
+ // Cornerstone's ECGViewport can retrieve it via metaData.get('ecgModule', imageId).
23694
+ if (imageId) {
23695
+ const ecgModule = buildEcgModule(instance, userAuthenticationService);
23696
+ if (ecgModule) {
23697
+ esm.utilities.genericMetadataProvider.addRaw(imageId, {
23698
+ type: MetadataModules.ECG,
23699
+ metadata: ecgModule
23700
+ });
23701
+ }
23702
+ }
23703
+ return {
23704
+ Modality,
23705
+ displaySetInstanceUID: getSopClassHandlerModule_utils.guid(),
23706
+ SeriesDescription,
23707
+ SeriesNumber,
23708
+ SeriesDate,
23709
+ SOPInstanceUID,
23710
+ SeriesInstanceUID,
23711
+ StudyInstanceUID,
23712
+ SOPClassHandlerId: DicomEcgSOPClassHandlerId,
23713
+ SOPClassUID,
23714
+ referencedImages: null,
23715
+ measurements: null,
23716
+ viewportType: esm.Enums.ViewportType.ECG,
23717
+ instances: [instance],
23718
+ instance,
23719
+ thumbnailSrc: null,
23720
+ isDerivedDisplaySet: false,
23721
+ isLoaded: false,
23722
+ sopClassUids: ecgSopClassUids,
23723
+ numImageFrames: 0,
23724
+ numInstances: 1,
23725
+ imageIds: imageId ? [imageId] : [],
23726
+ supportsWindowLevel: false,
23727
+ label: SeriesDescription || 'ECG'
23728
+ };
23729
+ });
23730
+ }
23731
+ function getDicomEcgSopClassHandler({
23732
+ servicesManager
23733
+ }) {
23734
+ const getDisplaySetsFromSeries = instances => _getEcgDisplaySetsFromSeries(instances, servicesManager);
23735
+ return {
23736
+ name: 'DicomEcgSopClassHandler',
23737
+ sopClassUids: ecgSopClassUids,
23738
+ getDisplaySetsFromSeries
23739
+ };
23740
+ }
23396
23741
  function getSopClassHandlerModule(params) {
23397
- return [getDicomMicroscopySopClassHandler(params)];
23742
+ return [getDicomMicroscopySopClassHandler(params), getDicomEcgSopClassHandler(params)];
23398
23743
  }
23399
23744
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/hooks/useActiveViewportSegmentationRepresentations.ts
23400
23745
  var useActiveViewportSegmentationRepresentations = __webpack_require__(9234);
@@ -23424,7 +23769,7 @@ function SegmentationUtilityButton(props) {
23424
23769
  isActive,
23425
23770
  id
23426
23771
  } = props;
23427
- const activeSegmentationUtility = (0,default_src.useUIStateStore)(store => store.uiState.activeSegmentationUtility);
23772
+ const activeSegmentationUtility = (0,default_src/* useUIStateStore */.FS)(store => store.uiState.activeSegmentationUtility);
23428
23773
  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
23774
  const handleMouseDownCapture = (0,react.useCallback)(event => {
23430
23775
  if (activeSegmentationUtility === id) {
@@ -23555,7 +23900,7 @@ function PanelSegmentation({
23555
23900
  segmentationsWithRepresentations,
23556
23901
  disabled
23557
23902
  } = (0,useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c)();
23558
- const setUIState = (0,default_src.useUIStateStore)(store => store.setUIState);
23903
+ const setUIState = (0,default_src/* useUIStateStore */.FS)(store => store.setUIState);
23559
23904
 
23560
23905
  // useEffect for handling clicks on any of the non-active viewports.
23561
23906
  // The ViewportGrid stops the propagation of pointer/mouse events
@@ -23816,7 +24161,7 @@ function PanelSegmentation({
23816
24161
  IconContainer: components_SegmentationUtilityButton
23817
24162
  }, /*#__PURE__*/react.createElement("div", {
23818
24163
  className: "flex flex-wrap gap-[3px] bg-transparent pb-[2px] pl-[8px] pt-[6px]"
23819
- }, /*#__PURE__*/react.createElement(default_src.Toolbar, {
24164
+ }, /*#__PURE__*/react.createElement(default_src/* Toolbar */.M7, {
23820
24165
  buttonSection: buttonSection
23821
24166
  })));
23822
24167
  };
@@ -24343,12 +24688,12 @@ function DefaultAccordion(props) {
24343
24688
  if (!allChildren || !groups) {
24344
24689
  return null;
24345
24690
  }
24346
- if (Boolean(asChild)) {
24691
+ if (asChild) {
24347
24692
  return /*#__PURE__*/react.cloneElement(props.children, props);
24348
24693
  }
24349
24694
  return /*#__PURE__*/react.createElement(ui_next_src/* Accordion */.nD3, {
24350
24695
  type: grouping.type || 'multiple',
24351
- className: "text-white",
24696
+ className: "text-foreground",
24352
24697
  defaultValue: defaultValue
24353
24698
  }, [...groups.entries()].map(([key, group]) => {
24354
24699
  return /*#__PURE__*/react.createElement(ui_next_src/* AccordionItem */.AsP, {
@@ -24826,7 +25171,7 @@ function PanelMeasurement(props) {
24826
25171
  return EmptyComponent ? /*#__PURE__*/react.createElement(EmptyComponent, {
24827
25172
  items: displayMeasurements
24828
25173
  }) : /*#__PURE__*/react.createElement("span", {
24829
- className: "text-white"
25174
+ className: "text-foreground"
24830
25175
  }, "No Measurements");
24831
25176
  }
24832
25177
  if (children) {
@@ -24891,7 +25236,7 @@ const getPanelModule = ({
24891
25236
  } = (0,es/* useTranslation */.Bd)('SegmentationPanel');
24892
25237
  const tKey = `${props.segmentationRepresentationTypes?.[0] ?? 'Segmentation'} tools`;
24893
25238
  const tValue = t(tKey);
24894
- return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src.Toolbox, {
25239
+ return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src/* Toolbox */.OO, {
24895
25240
  buttonSectionId: toolSectionMap[props.segmentationRepresentationTypes?.[0]],
24896
25241
  title: tValue
24897
25242
  }), /*#__PURE__*/react.createElement(PanelSegmentation, {
@@ -25245,7 +25590,7 @@ function promptHydrationDialog({
25245
25590
  customizationService
25246
25591
  } = servicesManager.services;
25247
25592
  const extensionManager = servicesManager._extensionManager;
25248
- const appConfig = extensionManager._appConfig;
25593
+ const appConfig = extensionManager.appConfig;
25249
25594
 
25250
25595
  // Todo: make this use enum from the extension, we should move the enum
25251
25596
  const standardMode = appConfig?.measurementTrackingMode === 'standard';
@@ -25262,20 +25607,30 @@ function promptHydrationDialog({
25262
25607
  if (type === HydrationType.SEG) {
25263
25608
  // SEG needs setTimeout
25264
25609
  window.setTimeout(async () => {
25265
- const isHydrated = await hydrateCallback({
25266
- segDisplaySet: displaySet,
25267
- viewportId
25268
- });
25269
- resolve(isHydrated);
25610
+ try {
25611
+ const isHydrated = await hydrateCallback({
25612
+ segDisplaySet: displaySet,
25613
+ viewportId
25614
+ });
25615
+ resolve(isHydrated);
25616
+ } catch (error) {
25617
+ reject(error);
25618
+ }
25270
25619
  }, 0);
25271
25620
  } else if (type === HydrationType.RTSTRUCT) {
25272
25621
  // RT hydration
25273
- const isHydrated = await hydrateCallback({
25274
- rtDisplaySet: displaySet,
25275
- viewportId,
25276
- servicesManager
25277
- });
25278
- resolve(isHydrated);
25622
+ window.setTimeout(async () => {
25623
+ try {
25624
+ const isHydrated = await hydrateCallback({
25625
+ rtDisplaySet: displaySet,
25626
+ viewportId,
25627
+ servicesManager
25628
+ });
25629
+ resolve(isHydrated);
25630
+ } catch (error) {
25631
+ reject(error);
25632
+ }
25633
+ }, 0);
25279
25634
  } else if (type === HydrationType.SR) {
25280
25635
  // SR has a different result structure
25281
25636
  const hydrationResult = await hydrateCallback(displaySet);
@@ -25368,7 +25723,8 @@ const setUpSegmentationEventHandlers = ({
25368
25723
  const {
25369
25724
  segmentationService,
25370
25725
  customizationService,
25371
- displaySetService
25726
+ displaySetService,
25727
+ viewportGridService
25372
25728
  } = servicesManager.services;
25373
25729
  const {
25374
25730
  unsubscribe: unsubscribeSegmentationDataModifiedHandler
@@ -25413,12 +25769,42 @@ const setUpSegmentationEventHandlers = ({
25413
25769
  };
25414
25770
  displaySetService.addDisplaySets(segmentationDisplaySet);
25415
25771
  });
25772
+ const {
25773
+ unsubscribe: unsubscribeSegmentationRemoved
25774
+ } = segmentationService.subscribe(segmentationService.EVENTS.SEGMENTATION_REMOVED, ({
25775
+ segmentationId
25776
+ }) => {
25777
+ const displaySet = displaySetService.getDisplaySetByUID(segmentationId);
25778
+
25779
+ // Remove the display set layer from all viewports that have it
25780
+ if (displaySet) {
25781
+ const state = viewportGridService.getState();
25782
+ const viewports = state.viewports;
25783
+
25784
+ // Find all viewports that contain this segmentation's display set as a layer
25785
+ for (const [viewportId, viewport] of viewports.entries()) {
25786
+ const displaySetInstanceUIDs = viewport.displaySetInstanceUIDs || [];
25787
+ if (displaySetInstanceUIDs.includes(segmentationId)) {
25788
+ // Remove the display set layer from this viewport
25789
+ commandsManager.runCommand('removeDisplaySetLayer', {
25790
+ viewportId,
25791
+ displaySetInstanceUID: segmentationId
25792
+ });
25793
+ }
25794
+ }
25795
+
25796
+ // Delete the display set from the service if it was made in client
25797
+ if (displaySet.madeInClient) {
25798
+ displaySetService.deleteDisplaySet(segmentationId);
25799
+ }
25800
+ }
25801
+ });
25416
25802
  const {
25417
25803
  unsubscribeSelectedSegmentationsForViewportEvents
25418
25804
  } = setUpSelectedSegmentationsForViewportHandler({
25419
25805
  segmentationService
25420
25806
  });
25421
- const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, ...unsubscribeSelectedSegmentationsForViewportEvents];
25807
+ const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, unsubscribeSegmentationRemoved, ...unsubscribeSelectedSegmentationsForViewportEvents];
25422
25808
  return {
25423
25809
  unsubscriptions
25424
25810
  };
@@ -25561,7 +25947,7 @@ function PanelAccordionTrigger(props) {
25561
25947
  }, /*#__PURE__*/react.createElement("button", {
25562
25948
  onClick: onClickDefault.bind(props)
25563
25949
  }, /*#__PURE__*/react.createElement("span", {
25564
- className: `inline-flex rounded-l border-r border-black ${isActive ? 'bg-highlight' : 'bg-muted'}`
25950
+ className: `inline-flex rounded-l border-r border-background ${isActive ? 'bg-highlight' : 'bg-muted'}`
25565
25951
  }, count !== undefined ? /*#__PURE__*/react.createElement("span", {
25566
25952
  className: "px-2"
25567
25953
  }, count) : null, colorHex && /*#__PURE__*/react.createElement(ui_next_src/* ColorCircle */.cd8, {
@@ -25810,13 +26196,14 @@ function src_extends() { return src_extends = Object.assign ? Object.assign.bind
25810
26196
 
25811
26197
 
25812
26198
 
26199
+
25813
26200
 
25814
26201
 
25815
26202
  const {
25816
26203
  imageRetrieveMetadataProvider
25817
26204
  } = esm.utilities;
25818
26205
  const Component = /*#__PURE__*/react.lazy(() => {
25819
- return __webpack_require__.e(/* import() */ 147).then(__webpack_require__.bind(__webpack_require__, 30147));
26206
+ return __webpack_require__.e(/* import() */ 3754).then(__webpack_require__.bind(__webpack_require__, 33754));
25820
26207
  });
25821
26208
  const OHIFCornerstoneViewport = props => {
25822
26209
  return /*#__PURE__*/react.createElement(react.Suspense, {
@@ -25909,9 +26296,10 @@ const cornerstoneExtension = {
25909
26296
  useLutPresentationStore/* useLutPresentationStore */.I.getState().clearLutPresentationStore();
25910
26297
  usePositionPresentationStore/* usePositionPresentationStore */.q.getState().clearPositionPresentationStore();
25911
26298
  useSynchronizersStore/* useSynchronizersStore */.U.getState().clearSynchronizersStore();
25912
- default_src.useToggleOneUpViewportGridStore.getState().clearToggleOneUpViewportGridStore();
26299
+ default_src/* useToggleOneUpViewportGridStore */.Yd.getState().clearToggleOneUpViewportGridStore();
25913
26300
  useSegmentationPresentationStore/* useSegmentationPresentationStore */.v.getState().clearSegmentationPresentationStore();
25914
26301
  useSelectedSegmentationsForViewportStore.getState().clearSelectedSegmentationsForViewportStore();
26302
+ servicesManager.services.viewedDataService?.clearViewedData();
25915
26303
  segmentationService.removeAllSegmentations();
25916
26304
  },
25917
26305
  /**
@@ -25929,6 +26317,7 @@ const cornerstoneExtension = {
25929
26317
  servicesManager.registerService(services_SegmentationService.REGISTRATION);
25930
26318
  servicesManager.registerService(services_CornerstoneCacheService.REGISTRATION);
25931
26319
  servicesManager.registerService(services_ColorbarService.REGISTRATION);
26320
+ servicesManager.registerService(services_ViewedDataService.REGISTRATION);
25932
26321
  const {
25933
26322
  syncGroupService
25934
26323
  } = servicesManager.services;
@@ -26000,10 +26389,10 @@ const cornerstoneExtension = {
26000
26389
 
26001
26390
  /* harmony default export */ const cornerstone_src = (cornerstoneExtension);
26002
26391
 
26003
- /***/ }),
26392
+ /***/ },
26004
26393
 
26005
- /***/ 71353:
26006
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26394
+ /***/ 71353
26395
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26007
26396
 
26008
26397
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26009
26398
  /* harmony export */ cL: () => (/* binding */ reset),
@@ -26042,10 +26431,10 @@ const reset = () => {
26042
26431
  };
26043
26432
 
26044
26433
 
26045
- /***/ }),
26434
+ /***/ },
26046
26435
 
26047
- /***/ 46026:
26048
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26436
+ /***/ 46026
26437
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26049
26438
 
26050
26439
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26051
26440
  /* harmony export */ FG: () => (/* binding */ JOIN_STR),
@@ -26085,10 +26474,10 @@ const addUniqueIndex = (arr, key, viewports, isUpdatingSameViewport) => {
26085
26474
  };
26086
26475
 
26087
26476
 
26088
- /***/ }),
26477
+ /***/ },
26089
26478
 
26090
- /***/ 10182:
26091
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26479
+ /***/ 10182
26480
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26092
26481
 
26093
26482
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26094
26483
  /* harmony export */ I: () => (/* binding */ useLutPresentationStore)
@@ -26200,10 +26589,10 @@ const useLutPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .creat
26200
26589
  name: 'LutPresentationStore'
26201
26590
  }) : createLutPresentationStore);
26202
26591
 
26203
- /***/ }),
26592
+ /***/ },
26204
26593
 
26205
- /***/ 44646:
26206
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26594
+ /***/ 44646
26595
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26207
26596
 
26208
26597
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26209
26598
  /* harmony export */ q: () => (/* binding */ usePositionPresentationStore)
@@ -26311,10 +26700,10 @@ const usePositionPresentationStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .
26311
26700
  name: 'PositionPresentationStore'
26312
26701
  }) : createPositionPresentationStore);
26313
26702
 
26314
- /***/ }),
26703
+ /***/ },
26315
26704
 
26316
- /***/ 2847:
26317
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26705
+ /***/ 2847
26706
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26318
26707
 
26319
26708
 
26320
26709
  // EXPORTS
@@ -26520,10 +26909,10 @@ const useSegmentationPresentationStore = (0,esm/* create */.vt)()(DEBUG_STORE ?
26520
26909
  name: 'Segmentation Presentation Store'
26521
26910
  }) : createSegmentationPresentationStore);
26522
26911
 
26523
- /***/ }),
26912
+ /***/ },
26524
26913
 
26525
- /***/ 68578:
26526
- /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
26914
+ /***/ 68578
26915
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26527
26916
 
26528
26917
  /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26529
26918
  /* harmony export */ U: () => (/* binding */ useSynchronizersStore)
@@ -26584,6 +26973,32 @@ const useSynchronizersStore = (0,zustand__WEBPACK_IMPORTED_MODULE_0__/* .create
26584
26973
  name: 'SynchronizersStore'
26585
26974
  }) : createSynchronizersStore);
26586
26975
 
26587
- /***/ })
26976
+ /***/ },
26977
+
26978
+ /***/ 67142
26979
+ (__unused_webpack_module, __webpack_exports__, __webpack_require__) {
26980
+
26981
+ /* harmony export */ __webpack_require__.d(__webpack_exports__, {
26982
+ /* harmony export */ V: () => (/* binding */ getDataIdForViewport)
26983
+ /* harmony export */ });
26984
+ /**
26985
+ * Resolves the data ID (e.g. volumeId) for a viewport and display set.
26986
+ * For viewports with multiple volumes/actors, returns the id that matches the display set; otherwise undefined.
26987
+ * Use this to call viewport.getProperties(dataId) in a viewport-type-agnostic way.
26988
+ *
26989
+ * @param viewport - Viewport instance (stack, volume, or future types with optional getAllVolumeIds)
26990
+ * @param displaySetInstanceUID - Display set instance UID to match
26991
+ * @returns volumeId (or equivalent) for multi-actor viewports, undefined for single-actor
26992
+ */
26993
+ function getDataIdForViewport(viewport, displaySetInstanceUID) {
26994
+ const vp = viewport;
26995
+ if (typeof vp.getAllVolumeIds !== 'function') {
26996
+ return undefined;
26997
+ }
26998
+ const volumeIds = vp.getAllVolumeIds() || [];
26999
+ return volumeIds.length > 0 ? volumeIds.find(id => id.includes(displaySetInstanceUID)) ?? undefined : undefined;
27000
+ }
27001
+
27002
+ /***/ }
26588
27003
 
26589
27004
  }]);