@ohif/app 3.12.0-beta.99 → 3.12.0

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 (52) hide show
  1. package/dist/{1403.bundle.94a178e2572f1f0b2a2c.js → 1403.bundle.1c9ce804d1e88033e276.js} +4 -2
  2. package/dist/{147.bundle.205350dc3d21478277b1.js → 147.bundle.37d627289453cb6c3937.js} +6 -15
  3. package/dist/{1608.bundle.f855c4bdb7f00eb66fca.js → 1608.bundle.0687c661f1c9edfb3b8a.js} +4 -4
  4. package/dist/{1730.bundle.37c569ae3ed057b69840.js → 1730.bundle.66a5e554ab20dab97b11.js} +7 -5
  5. package/dist/{1927.bundle.019331c266d306772371.js → 1927.bundle.3050588e95f43cf57cdd.js} +1 -1
  6. package/dist/{1933.bundle.ab5e8036f6e1c854c965.js → 1933.bundle.682f142e3217d4c7fbf7.js} +7 -3
  7. package/dist/{2018.bundle.469f9ad42597b6b29ff1.js → 2018.bundle.c06693143228cc034cb9.js} +47 -47
  8. package/dist/{213.bundle.398730bb3ceb1af54413.js → 213.bundle.c2d4d7370c26b0823880.js} +2 -2
  9. package/dist/{2424.bundle.be90e7bcf0fd8db68b2f.js → 2424.bundle.c1e287e752f352b76543.js} +2 -2
  10. package/dist/{2701.bundle.aca0d4f24a6f2094c3c3.js → 2701.bundle.12bd01a80a9f8ea4cd94.js} +4 -4
  11. package/dist/{2842.bundle.7852a204d3510fca8b27.js → 2842.bundle.860b9f10fcdd9656947a.js} +330 -123
  12. package/dist/{1903.bundle.dc5248f7cb6ba1dc1072.js → 3081.bundle.41838985e0472851eadb.js} +644 -322
  13. package/dist/{3343.bundle.f8fe9316b0ff68d087f7.js → 3343.bundle.d7578ce8f75d158c0bab.js} +2 -0
  14. package/dist/{3461.bundle.50c752c623f39cf6c457.js → 3461.bundle.a8fcefd1c6e389d905fc.js} +21 -17
  15. package/dist/{3584.bundle.839a16d349815b3f7c97.js → 3584.bundle.8cc0750425513433e9cc.js} +15 -17
  16. package/dist/{4019.bundle.01f63d5dd5b96ded0c00.js → 4019.bundle.83a604779f7da0101ced.js} +196 -366
  17. package/dist/{4202.bundle.790706560c6edb303476.js → 4202.bundle.5a0f8e4004c5d8a68548.js} +2 -2
  18. package/dist/{5448.bundle.9a36e001169ea3bfeb6c.js → 4410.bundle.c5224cd7d6238a7d4660.js} +313 -57
  19. package/dist/{4775.bundle.d7f0645419f1df8e00b8.js → 4775.bundle.70bc407db26afaa4331a.js} +24 -16
  20. package/dist/{4819.bundle.ef1151f023b3784bc1be.js → 4819.bundle.47e7aa44747ddab3a39a.js} +8 -6
  21. package/dist/{5028.bundle.b3611b7c7422a5c2e723.js → 5028.bundle.274945a9ae69c6b6ad51.js} +6 -6
  22. package/dist/{5462.bundle.a81a691eeef782ab95b9.js → 5462.bundle.21beddaca145b7465c72.js} +2 -0
  23. package/dist/{5485.bundle.71041ca4bc9e6ab57d92.js → 5485.bundle.4e0ec03c61ec5cadd9bb.js} +3 -3
  24. package/dist/{5802.bundle.28ab859d9b48a5b2c31c.js → 5802.bundle.3bf5e6b3ab330a594a47.js} +6 -12
  25. package/dist/{6163.bundle.1f096bdbe3a341c1710d.js → 6163.bundle.ca93a4e6501880901f94.js} +4 -2
  26. package/dist/{3353.bundle.a0f1654c642395bbbbbc.js → 6347.bundle.784c48912700f281de1d.js} +323 -179
  27. package/dist/{5400.bundle.de97508611da1c00d58a.js → 6409.bundle.b36048896cb11c8571fb.js} +450 -79
  28. package/dist/{7412.bundle.aec4834a71fc27c4ce06.js → 7412.bundle.fab1742191b7fe937330.js} +251 -197
  29. package/dist/{7431.bundle.999b2b65d4973bc56218.js → 7431.bundle.b01791d10e6cf9f503b0.js} +10 -4
  30. package/dist/{7639.bundle.e004d734044049fe8fe9.js → 7639.bundle.32152cacb059089ed7d7.js} +24 -20
  31. package/dist/{8305.bundle.ba43ed23edea2bf394b3.js → 8305.bundle.2ede68ba3c075928c9f4.js} +47 -29
  32. package/dist/{8558.bundle.463ddb34a619cf47493e.js → 8558.bundle.3e84c4ba2c7ec6fce52c.js} +33 -3
  33. package/dist/{8583.bundle.59c239cf891c2e10bf10.js → 8583.bundle.2908eee785e7e4595d14.js} +28 -23
  34. package/dist/{9195.bundle.e2fd5c6b5830c0ee25a8.js → 9195.bundle.606ca286a0fed8a43f58.js} +146 -73
  35. package/dist/{9845.bundle.31aec3fe7a5cdc247f4e.js → 9845.bundle.255e7c7f7a88193b4e47.js} +16 -8
  36. package/dist/{9862.bundle.3ca0ad5f54db87ccf91e.js → 9862.bundle.3a8958a82c572015d25d.js} +2 -2
  37. package/dist/{9927.bundle.f421cd167be94a7109f6.js → 9927.bundle.e798a347dfe1f241578f.js} +16 -16
  38. package/dist/{5549.bundle.d5def6a3124a3a481b7c.js → 997.bundle.822b33e561263084e18c.js} +961 -290
  39. package/dist/{app.bundle.7df5bc1cd812bd602686.js → app.bundle.26b7eafdf05b5445414b.js} +5893 -2247
  40. package/dist/app.bundle.css +1 -1
  41. package/dist/{compute.bundle.fdee4a0f193ee2e1b6da.js → compute.bundle.64280c7af19ff567465f.js} +3 -3
  42. package/dist/dicom-microscopy-viewer/dicomMicroscopyViewer.min.js +3254 -1792
  43. package/dist/dicom-microscopy-viewer/dicomMicroscopyViewer.min.js.map +1 -1
  44. package/dist/index.html +1 -1
  45. package/dist/{polySeg.bundle.11f9746cd60c9811a412.js → polySeg.bundle.a5aa9130b4191253c410.js} +3 -3
  46. package/dist/sw.js +1 -1
  47. package/package.json +24 -24
  48. /package/dist/{1459.bundle.3785cdd0abf449adebf1.js → 1459.bundle.e8802999a4d7f7edf628.js} +0 -0
  49. /package/dist/{5457.bundle.9f2eb65ad85fcbb75e27.js → 5457.bundle.f7de73bcfe1012a73b9f.js} +0 -0
  50. /package/dist/{5858.bundle.d5f4bf849aaeebf5025c.js → 5858.bundle.ff6b340cf7457db76a1a.js} +0 -0
  51. /package/dist/{6027.bundle.160bd47ea03784276275.js → 6027.bundle.2b12862684b0cb3af4b4.js} +0 -0
  52. /package/dist/{85.bundle.a16e254910c60223df19.js → 85.bundle.05591d5a14d74a502dfe.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[1903],{
2
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[3081],{
3
3
 
4
4
  /***/ 38007:
5
5
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
@@ -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 + 3073 modules
29
- var src = __webpack_require__(1246);
28
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3075 modules
29
+ var src = __webpack_require__(12517);
30
30
  ;// ../../../extensions/cornerstone/src/hooks/useViewportHover.ts
31
31
 
32
32
 
@@ -117,7 +117,7 @@ var useViewportRendering = __webpack_require__(47488);
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__(1246);
120
+ /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(12517);
121
121
  /* harmony import */ var _useViewportSegmentations__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(79063);
122
122
 
123
123
 
@@ -250,6 +250,8 @@ function useMeasurementTracking({
250
250
  /* harmony import */ var lodash_debounce__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(62051);
251
251
  /* harmony import */ var lodash_debounce__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(lodash_debounce__WEBPACK_IMPORTED_MODULE_1__);
252
252
  /* harmony import */ var _ohif_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(42356);
253
+ /* harmony import */ var _ohif_i18n__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(89010);
254
+
253
255
 
254
256
 
255
257
 
@@ -268,7 +270,7 @@ function mapMeasurementToDisplay(measurement, displaySetService) {
268
270
  displayText: baseDisplayText
269
271
  } = measurement;
270
272
  const firstSite = findingSites?.[0];
271
- const label = baseLabel || finding?.text || firstSite?.text || '(empty)';
273
+ const label = baseLabel || finding?.text || firstSite?.text || _ohif_i18n__WEBPACK_IMPORTED_MODULE_3__/* ["default"] */ .A.t('MeasurementTable:empty');
272
274
 
273
275
  // Initialize displayText with the structure used in Length.ts and CobbAngle.ts
274
276
  const displayText = {
@@ -496,8 +498,8 @@ __webpack_require__.d(__webpack_exports__, {
496
498
  var react = __webpack_require__(86326);
497
499
  // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
498
500
  var src = __webpack_require__(42356);
499
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3073 modules
500
- var ui_next_src = __webpack_require__(1246);
501
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3075 modules
502
+ var ui_next_src = __webpack_require__(12517);
501
503
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 1 modules
502
504
  var esm = __webpack_require__(15327);
503
505
  ;// ../../../extensions/cornerstone/src/components/ViewportDataOverlaySettingMenu/utils.ts
@@ -1657,7 +1659,7 @@ function useViewportSegmentations({
1657
1659
 
1658
1660
  /***/ }),
1659
1661
 
1660
- /***/ 71903:
1662
+ /***/ 63081:
1661
1663
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1662
1664
 
1663
1665
  // ESM COMPAT FLAG
@@ -6985,8 +6987,8 @@ var useLutPresentationStore = __webpack_require__(10182);
6985
6987
  var usePositionPresentationStore = __webpack_require__(44646);
6986
6988
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/stores/useSegmentationPresentationStore.ts + 1 modules
6987
6989
  var useSegmentationPresentationStore = __webpack_require__(2847);
6988
- // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/index.js + 46 modules
6989
- var esm_utilities = __webpack_require__(33592);
6990
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/utilities/index.js + 47 modules
6991
+ var esm_utilities = __webpack_require__(85343);
6990
6992
  ;// ../../../extensions/cornerstone/src/utils/initWebWorkerProgressHandler.ts
6991
6993
 
6992
6994
 
@@ -7471,8 +7473,8 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
7471
7473
  inheritsFrom: 'ohif.overlayItem.instanceNumber'
7472
7474
  }]
7473
7475
  });
7474
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3073 modules
7475
- var ui_next_src = __webpack_require__(1246);
7476
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3075 modules
7477
+ var ui_next_src = __webpack_require__(12517);
7476
7478
  // EXTERNAL MODULE: ../../../node_modules/react-i18next/dist/es/index.js + 15 modules
7477
7479
  var es = __webpack_require__(99993);
7478
7480
  ;// ../../../extensions/cornerstone/src/components/ExportSegmentationSubMenuItem.tsx
@@ -7488,7 +7490,7 @@ const ExportSegmentationSubMenuItem = ({
7488
7490
  }) => {
7489
7491
  const {
7490
7492
  t
7491
- } = (0,es/* useTranslation */.Bd)('SegmentationTable');
7493
+ } = (0,es/* useTranslation */.Bd)('SegmentationPanel');
7492
7494
  return /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSub */.lvB, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubTrigger */.nVd, {
7493
7495
  className: "pl-1"
7494
7496
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
@@ -7555,7 +7557,7 @@ const CustomDropdownMenuContent = () => {
7555
7557
  } = (0,src/* useSystem */.Jg)();
7556
7558
  const {
7557
7559
  t
7558
- } = (0,es/* useTranslation */.Bd)('SegmentationTable');
7560
+ } = (0,es/* useTranslation */.Bd)('SegmentationPanel');
7559
7561
  const {
7560
7562
  onSegmentationAdd,
7561
7563
  onSegmentationRemoveFromViewport,
@@ -7564,7 +7566,7 @@ const CustomDropdownMenuContent = () => {
7564
7566
  exportOptions,
7565
7567
  activeSegmentation,
7566
7568
  activeSegmentationId,
7567
- segmentationRepresentationType,
7569
+ segmentationRepresentationTypes,
7568
7570
  disableEditing
7569
7571
  } = (0,ui_next_src/* useSegmentationTableContext */.dQ$)('CustomDropdownMenu');
7570
7572
 
@@ -7623,7 +7625,7 @@ const CustomDropdownMenuContent = () => {
7623
7625
  }, !disableEditing && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7624
7626
  onClick: () => onSegmentationAdd({
7625
7627
  segmentationId,
7626
- segmentationRepresentationType
7628
+ segmentationRepresentationType: segmentationRepresentationTypes?.[0]
7627
7629
  })
7628
7630
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Add, {
7629
7631
  className: "text-foreground"
@@ -7643,7 +7645,7 @@ const CustomDropdownMenuContent = () => {
7643
7645
  className: "pl-2"
7644
7646
  }, t('Rename'))), /*#__PURE__*/react.createElement(ExportSegmentationSubMenuItem, {
7645
7647
  segmentationId: segmentationId,
7646
- segmentationRepresentationType: segmentationRepresentationType,
7648
+ segmentationRepresentationType: segmentationRepresentationTypes?.[0],
7647
7649
  allowExport: allowExport,
7648
7650
  actions: actions
7649
7651
  }), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
@@ -7677,7 +7679,7 @@ const CustomSegmentStatisticsHeader = ({
7677
7679
  } = servicesManager.services;
7678
7680
  const {
7679
7681
  t
7680
- } = (0,es/* useTranslation */.Bd)('SegmentationTable');
7682
+ } = (0,es/* useTranslation */.Bd)('SegmentationPanel');
7681
7683
  const segmentation = segmentationService.getSegmentation(segmentationId);
7682
7684
  const segment = segmentation.segments[segmentIndex];
7683
7685
  const cachedStats = segment.cachedStats;
@@ -7770,10 +7772,14 @@ const CustomSegmentStatisticsHeader = ({
7770
7772
 
7771
7773
 
7772
7774
 
7775
+
7773
7776
  function SegmentationToolConfig() {
7774
7777
  const {
7775
7778
  commandsManager
7776
7779
  } = (0,src/* useSystem */.Jg)();
7780
+ const {
7781
+ t
7782
+ } = (0,es/* useTranslation */.Bd)('SegmentationPanel');
7777
7783
 
7778
7784
  // Get initial states based on current configuration
7779
7785
  const [previewEdits, setPreviewEdits] = (0,react.useState)(false);
@@ -7813,28 +7819,28 @@ function SegmentationToolConfig() {
7813
7819
  onCheckedChange: handlePreviewEditsChange
7814
7820
  }), /*#__PURE__*/react.createElement("span", {
7815
7821
  className: "text-foreground text-base"
7816
- }, "Preview edits before creating")), /*#__PURE__*/react.createElement("div", {
7822
+ }, t('Preview edits before creating'))), /*#__PURE__*/react.createElement("div", {
7817
7823
  className: "flex items-center gap-2"
7818
7824
  }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7819
7825
  checked: useCenterAsSegmentIndex,
7820
7826
  onCheckedChange: handleUseCenterAsSegmentIndexChange
7821
7827
  }), /*#__PURE__*/react.createElement("span", {
7822
7828
  className: "text-foreground text-base"
7823
- }, "Use center as segment index")), /*#__PURE__*/react.createElement("div", {
7829
+ }, t('Use center as segment index'))), /*#__PURE__*/react.createElement("div", {
7824
7830
  className: "flex items-center gap-2"
7825
7831
  }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7826
7832
  checked: toggleSegmentEnabled,
7827
7833
  onCheckedChange: handleToggleSegmentEnabledChange
7828
7834
  }), /*#__PURE__*/react.createElement("span", {
7829
7835
  className: "text-foreground text-base"
7830
- }, "Hover on segment border to activate")), /*#__PURE__*/react.createElement("div", {
7836
+ }, t('Hover on segment border to activate'))), /*#__PURE__*/react.createElement("div", {
7831
7837
  className: "flex items-center gap-2"
7832
7838
  }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7833
7839
  checked: segmentLabelEnabled,
7834
7840
  onCheckedChange: handleSegmentLabelEnabledChange
7835
7841
  }), /*#__PURE__*/react.createElement("span", {
7836
7842
  className: "text-foreground text-base"
7837
- }, "Show segment name on hover")));
7843
+ }, t('Show segment name on hover'))));
7838
7844
  }
7839
7845
  ;// ../../../extensions/cornerstone/src/customizations/segmentationPanelCustomization.tsx
7840
7846
 
@@ -9100,6 +9106,10 @@ function ViewportDownloadFormNew({
9100
9106
  })), /*#__PURE__*/react.createElement(ui_next_src/* ImageModal */.jiK.ImageSize, {
9101
9107
  width: dimensions.width.toString(),
9102
9108
  height: dimensions.height.toString(),
9109
+ widthLabel: t('Width'),
9110
+ heightLabel: t('Height'),
9111
+ widthPlaceholder: t('Width'),
9112
+ heightPlaceholder: t('Height'),
9103
9113
  onWidthChange: e => {
9104
9114
  onDimensionsChange({
9105
9115
  ...dimensions,
@@ -9114,9 +9124,7 @@ function ViewportDownloadFormNew({
9114
9124
  },
9115
9125
  maxWidth: MAX_TEXTURE_SIZE.toString(),
9116
9126
  maxHeight: MAX_TEXTURE_SIZE.toString()
9117
- }, t('Image size'), " ", /*#__PURE__*/react.createElement("span", {
9118
- className: "text-muted-foreground"
9119
- }, "px")), /*#__PURE__*/react.createElement(ui_next_src/* ImageModal */.jiK.SwitchOption, {
9127
+ }, t('Image size in pixels')), /*#__PURE__*/react.createElement(ui_next_src/* ImageModal */.jiK.SwitchOption, {
9120
9128
  defaultChecked: showAnnotations,
9121
9129
  checked: showAnnotations,
9122
9130
  onCheckedChange: onAnnotationsChange
@@ -9505,9 +9513,14 @@ const CornerstoneViewportDownloadForm = ({
9505
9513
  mode,
9506
9514
  bindings
9507
9515
  } = toolModeAndBindings[toolName];
9508
- toolGroup.setToolMode(toolName, mode, {
9509
- bindings
9510
- });
9516
+ try {
9517
+ toolGroup.setToolMode(toolName, mode, {
9518
+ bindings
9519
+ });
9520
+ } catch (error) {
9521
+ // Handle errors when restoring tool mode during cleanup (e.g., when tool state is undefined)
9522
+ console.debug('Error restoring tool mode during cleanup:', toolName, error);
9523
+ }
9511
9524
  });
9512
9525
  };
9513
9526
  }, []);
@@ -9557,7 +9570,7 @@ const CornerstoneViewportDownloadForm = ({
9557
9570
  volumeId: volumeIds[0]
9558
9571
  }]);
9559
9572
  }
9560
- if (segmentationRepresentations.length > 0) {
9573
+ if (segmentationRepresentations?.length) {
9561
9574
  segmentationRepresentations.forEach(segRepresentation => {
9562
9575
  const {
9563
9576
  segmentationId,
@@ -9638,14 +9651,17 @@ const CornerstoneViewportDownloadForm = ({
9638
9651
  }, 100);
9639
9652
  }
9640
9653
  }, [viewportDimensions, showAnnotations]);
9641
- const handleDownload = async (filename, fileType) => {
9654
+ const handleDownload = async (baseFilename, fileType) => {
9642
9655
  const divForDownloadViewport = document.querySelector(`div[data-viewport-uid="${VIEWPORT_ID}"]`);
9643
9656
  if (!divForDownloadViewport) {
9644
9657
  console.debug('No viewport found for download');
9645
9658
  return;
9646
9659
  }
9660
+ const filename = `${baseFilename}.${fileType}`;
9647
9661
  const canvas = await (0,html2canvas_esm/* default */.A)(divForDownloadViewport);
9648
- downloadUrl(canvas.toDataURL(`image/${fileType}`, 1.0));
9662
+ downloadUrl(canvas.toDataURL(`image/${fileType}`, 1.0), {
9663
+ filename
9664
+ });
9649
9665
  };
9650
9666
  const ViewportDownloadFormNew = customizationService.getCustomization('ohif.captureViewportModal');
9651
9667
  return /*#__PURE__*/react.createElement(ViewportDownloadFormNew, {
@@ -9707,6 +9723,11 @@ async function updateSegmentationStats({
9707
9723
  // Loop through each segment's stats
9708
9724
  Object.entries(stats).forEach(([segmentIndex, segmentStats]) => {
9709
9725
  const index = parseInt(segmentIndex);
9726
+ if (!updatedSegmentation.segments[index]) {
9727
+ // This happens when a segment is being restored
9728
+ console.warn('Segment not found to update cached stats:', index);
9729
+ return;
9730
+ }
9710
9731
  if (!updatedSegmentation.segments[index].cachedStats) {
9711
9732
  updatedSegmentation.segments[index].cachedStats = {};
9712
9733
  hasUpdates = true;
@@ -10317,8 +10338,8 @@ let EasingFunctionEnum = /*#__PURE__*/function (EasingFunctionEnum) {
10317
10338
  return EasingFunctionEnum;
10318
10339
  }({});
10319
10340
  const EasingFunctionMap = new Map([[EasingFunctionEnum.EASE, ease], [EasingFunctionEnum.EASE_IN, easeIn], [EasingFunctionEnum.EASE_OUT, easeOut], [EasingFunctionEnum.EASE_IN_OUT, easeInOut], [EasingFunctionEnum.LINEAR, linear]]);
10320
- // EXTERNAL MODULE: ../../i18n/src/index.js + 210 modules
10321
- var i18n_src = __webpack_require__(68523);
10341
+ // EXTERNAL MODULE: ../../i18n/src/index.js + 286 modules
10342
+ var i18n_src = __webpack_require__(89010);
10322
10343
  ;// ../../../extensions/cornerstone/src/utils/createSegmentationForViewport.ts
10323
10344
 
10324
10345
 
@@ -10523,6 +10544,42 @@ function commandsModule({
10523
10544
  }
10524
10545
  }
10525
10546
  }
10547
+
10548
+ /**
10549
+ * Creates a command function that sets a style property for segmentation types.
10550
+ * If type is provided, sets the property for that type only.
10551
+ * If type is not provided, sets the property for both Labelmap and Contour types.
10552
+ * @param propertyName - The name of the style property to set
10553
+ * @returns A command function that takes { type, value }
10554
+ */
10555
+ const createSetStyleCommand = propertyName => {
10556
+ return ({
10557
+ type,
10558
+ value
10559
+ }) => {
10560
+ const {
10561
+ segmentationService
10562
+ } = servicesManager.services;
10563
+ if (type) {
10564
+ segmentationService.setStyle({
10565
+ type
10566
+ }, {
10567
+ [propertyName]: value
10568
+ });
10569
+ } else {
10570
+ segmentationService.setStyle({
10571
+ type: esm_enums.SegmentationRepresentations.Labelmap
10572
+ }, {
10573
+ [propertyName]: value
10574
+ });
10575
+ segmentationService.setStyle({
10576
+ type: esm_enums.SegmentationRepresentations.Contour
10577
+ }, {
10578
+ [propertyName]: value
10579
+ });
10580
+ }
10581
+ };
10582
+ };
10526
10583
  const actions = {
10527
10584
  jumpToMeasurementViewport: ({
10528
10585
  annotationUID,
@@ -11965,7 +12022,7 @@ function commandsModule({
11965
12022
  animationFunctionType
11966
12023
  } = customizationService.getCustomization('panelSegmentation.jumpToSegmentHighlightAnimationConfig') ?? {};
11967
12024
  const validAnimationFunctionType = Object.values(EasingFunctionEnum).includes(animationFunctionType) ? animationFunctionType : undefined;
11968
- segmentationService.jumpToSegmentCenter(segmentationId, segmentIndex, undefined, highlightAlpha, highlightSegment, animationLength, undefined, validAnimationFunctionType);
12025
+ segmentationService.jumpToSegmentNext(segmentationId, segmentIndex, undefined, highlightAlpha, highlightSegment, animationLength, undefined, validAnimationFunctionType);
11969
12026
  },
11970
12027
  /**
11971
12028
  * Toggles the visibility of a segment
@@ -12139,146 +12196,6 @@ function commandsModule({
12139
12196
  const renderInactive = segmentationService.getRenderInactiveSegmentations(viewportId);
12140
12197
  segmentationService.setRenderInactiveSegmentations(viewportId, !renderInactive);
12141
12198
  },
12142
- /**
12143
- * Sets the fill alpha value for a segmentation type
12144
- * @param props.type - The type of segmentation
12145
- * @param props.value - The alpha value to set
12146
- */
12147
- setFillAlphaCommand: ({
12148
- type,
12149
- value
12150
- }) => {
12151
- const {
12152
- segmentationService
12153
- } = servicesManager.services;
12154
- segmentationService.setStyle({
12155
- type
12156
- }, {
12157
- fillAlpha: value
12158
- });
12159
- },
12160
- /**
12161
- * Sets the outline width for a segmentation type
12162
- * @param props.type - The type of segmentation
12163
- * @param props.value - The width value to set
12164
- */
12165
- setOutlineWidthCommand: ({
12166
- type,
12167
- value
12168
- }) => {
12169
- const {
12170
- segmentationService
12171
- } = servicesManager.services;
12172
- segmentationService.setStyle({
12173
- type
12174
- }, {
12175
- outlineWidth: value
12176
- });
12177
- },
12178
- /**
12179
- * Sets whether to render fill for a segmentation type
12180
- * @param props.type - The type of segmentation
12181
- * @param props.value - Whether to render fill
12182
- */
12183
- setRenderFillCommand: ({
12184
- type,
12185
- value
12186
- }) => {
12187
- const {
12188
- segmentationService
12189
- } = servicesManager.services;
12190
- segmentationService.setStyle({
12191
- type
12192
- }, {
12193
- renderFill: value
12194
- });
12195
- },
12196
- /**
12197
- * Sets whether to render fill for inactive segmentations of a segmentation type
12198
- * @param props.type - The type of segmentation
12199
- * @param props.value - Whether to render fill for inactive segmentations
12200
- */
12201
- setRenderFillInactiveCommand: ({
12202
- type,
12203
- value
12204
- }) => {
12205
- const {
12206
- segmentationService
12207
- } = servicesManager.services;
12208
- segmentationService.setStyle({
12209
- type
12210
- }, {
12211
- renderFillInactive: value
12212
- });
12213
- },
12214
- /**
12215
- * Sets whether to render outline for a segmentation type
12216
- * @param props.type - The type of segmentation
12217
- * @param props.value - Whether to render outline
12218
- */
12219
- setRenderOutlineCommand: ({
12220
- type,
12221
- value
12222
- }) => {
12223
- const {
12224
- segmentationService
12225
- } = servicesManager.services;
12226
- segmentationService.setStyle({
12227
- type
12228
- }, {
12229
- renderOutline: value
12230
- });
12231
- },
12232
- /**
12233
- * Sets whether to render outline for inactive segmentations of a segmentation type
12234
- * @param props.type - The type of segmentation
12235
- * @param props.value - Whether to render outline for inactive segmentations
12236
- */
12237
- setRenderOutlineInactiveCommand: ({
12238
- type,
12239
- value
12240
- }) => {
12241
- const {
12242
- segmentationService
12243
- } = servicesManager.services;
12244
- segmentationService.setStyle({
12245
- type
12246
- }, {
12247
- renderOutlineInactive: value
12248
- });
12249
- },
12250
- /**
12251
- * Sets the fill alpha for inactive segmentations.
12252
- * If no type is provided, the fill alpha for all types will be set.
12253
- * @param props.type - The type of segmentation
12254
- * @param props.value - The alpha value to set
12255
- */
12256
- setFillAlphaInactiveCommand: ({
12257
- type,
12258
- value
12259
- }) => {
12260
- const {
12261
- segmentationService
12262
- } = servicesManager.services;
12263
- if (type) {
12264
- segmentationService.setStyle({
12265
- type
12266
- }, {
12267
- fillAlphaInactive: value
12268
- });
12269
- } else {
12270
- segmentationService.setStyle({
12271
- type: esm_enums.SegmentationRepresentations.Labelmap
12272
- }, {
12273
- fillAlphaInactive: value
12274
- });
12275
- segmentationService.setStyle({
12276
- type: esm_enums.SegmentationRepresentations.Contour
12277
- }, {
12278
- fillAlphaInactive: value
12279
- });
12280
- }
12281
- },
12282
12199
  editSegmentLabel: async ({
12283
12200
  segmentationId,
12284
12201
  segmentIndex
@@ -13230,25 +13147,25 @@ function commandsModule({
13230
13147
  commandFn: actions.toggleRenderInactiveSegmentationsCommand
13231
13148
  },
13232
13149
  setFillAlpha: {
13233
- commandFn: actions.setFillAlphaCommand
13150
+ commandFn: createSetStyleCommand('fillAlpha')
13234
13151
  },
13235
13152
  setOutlineWidth: {
13236
- commandFn: actions.setOutlineWidthCommand
13153
+ commandFn: createSetStyleCommand('outlineWidth')
13237
13154
  },
13238
13155
  setRenderFill: {
13239
- commandFn: actions.setRenderFillCommand
13156
+ commandFn: createSetStyleCommand('renderFill')
13240
13157
  },
13241
13158
  setRenderFillInactive: {
13242
- commandFn: actions.setRenderFillInactiveCommand
13159
+ commandFn: createSetStyleCommand('renderFillInactive')
13243
13160
  },
13244
13161
  setRenderOutline: {
13245
- commandFn: actions.setRenderOutlineCommand
13162
+ commandFn: createSetStyleCommand('renderOutline')
13246
13163
  },
13247
13164
  setRenderOutlineInactive: {
13248
- commandFn: actions.setRenderOutlineInactiveCommand
13165
+ commandFn: createSetStyleCommand('renderOutlineInactive')
13249
13166
  },
13250
13167
  setFillAlphaInactive: {
13251
- commandFn: actions.setFillAlphaInactiveCommand
13168
+ commandFn: createSetStyleCommand('fillAlphaInactive')
13252
13169
  },
13253
13170
  editSegmentLabel: {
13254
13171
  commandFn: actions.editSegmentLabel
@@ -15391,6 +15308,7 @@ var hooks = __webpack_require__(38007);
15391
15308
 
15392
15309
 
15393
15310
 
15311
+
15394
15312
  function ViewportDataOverlayMenu({
15395
15313
  viewportId
15396
15314
  }) {
@@ -15398,6 +15316,9 @@ function ViewportDataOverlayMenu({
15398
15316
  commandsManager,
15399
15317
  servicesManager
15400
15318
  } = (0,src/* useSystem */.Jg)();
15319
+ const {
15320
+ t
15321
+ } = (0,es/* useTranslation */.Bd)();
15401
15322
  const [pendingForegrounds, setPendingForegrounds] = (0,react.useState)([]);
15402
15323
  const [pendingSegmentations, setPendingSegmentations] = (0,react.useState)([]);
15403
15324
  const {
@@ -15555,7 +15476,7 @@ function ViewportDataOverlayMenu({
15555
15476
  disabled: potentialForegroundDisplaySets.length === 0
15556
15477
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Plus, {
15557
15478
  className: "h-4 w-4"
15558
- }), "Foreground"), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
15479
+ }), t('Common:Foreground')), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
15559
15480
  variant: "ghost",
15560
15481
  className: "text-primary ml-2 flex items-center",
15561
15482
  disabled: potentialOverlayDisplaySets.length === 0,
@@ -15565,7 +15486,7 @@ function ViewportDataOverlayMenu({
15565
15486
  dataCY: `AddSegmentationDataOverlay-${viewportId}`
15566
15487
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Plus, {
15567
15488
  className: "h-4 w-4"
15568
- }), "Segmentation")), /*#__PURE__*/react.createElement("div", {
15489
+ }), t('Tools:Segmentation'))), /*#__PURE__*/react.createElement("div", {
15569
15490
  className: ""
15570
15491
  }, /*#__PURE__*/react.createElement("div", {
15571
15492
  className: "my-2 ml-1"
@@ -15618,7 +15539,7 @@ function ViewportDataOverlayMenu({
15618
15539
  }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
15619
15540
  className: "flex-1"
15620
15541
  }, /*#__PURE__*/react.createElement(ui_next_src/* SelectValue */.yvm, {
15621
- placeholder: "SELECT A SEGMENTATION"
15542
+ placeholder: t('Common:SELECT A SEGMENTATION')
15622
15543
  })), /*#__PURE__*/react.createElement(ui_next_src/* SelectContent */.gCo, null, potentialOverlayDisplaySets.map(item => /*#__PURE__*/react.createElement(ui_next_src/* SelectItem */.ebT, {
15623
15544
  key: item.displaySetInstanceUID,
15624
15545
  value: item.displaySetInstanceUID,
@@ -15688,7 +15609,7 @@ function ViewportDataOverlayMenu({
15688
15609
  }, /*#__PURE__*/react.createElement(ui_next_src/* SelectTrigger */.bqE, {
15689
15610
  className: "flex-1"
15690
15611
  }, /*#__PURE__*/react.createElement(ui_next_src/* SelectValue */.yvm, {
15691
- placeholder: "SELECT A FOREGROUND"
15612
+ placeholder: t('Common:SELECT A FOREGROUND')
15692
15613
  })), /*#__PURE__*/react.createElement(ui_next_src/* SelectContent */.gCo, null, potentialForegroundDisplaySets.map(item => /*#__PURE__*/react.createElement(ui_next_src/* SelectItem */.ebT, {
15693
15614
  key: item.displaySetInstanceUID,
15694
15615
  value: item.displaySetInstanceUID,
@@ -16131,7 +16052,9 @@ function Colormap({
16131
16052
  className: "p-1"
16132
16053
  }, colormaps.map((colormap, index) => /*#__PURE__*/react.createElement(ui_next_src/* AllInOneMenu */.se.Item, {
16133
16054
  key: index,
16134
- label: colormap.description,
16055
+ label: t(`Colormaps:${colormap.Name}`, {
16056
+ defaultValue: colormap.Name
16057
+ }),
16135
16058
  useIconSpace: false,
16136
16059
  onClick: () => {
16137
16060
  setCurrentColormap(colormap);
@@ -16188,9 +16111,13 @@ function Colorbar({
16188
16111
 
16189
16112
 
16190
16113
 
16114
+
16191
16115
  function WindowLevel({
16192
16116
  viewportId
16193
16117
  } = {}) {
16118
+ const {
16119
+ t
16120
+ } = (0,es/* useTranslation */.Bd)('WindowLevelActionMenu');
16194
16121
  const {
16195
16122
  viewportDisplaySets
16196
16123
  } = (0,useViewportRendering/* useViewportRendering */.e)(viewportId);
@@ -16242,7 +16169,7 @@ function WindowLevel({
16242
16169
  onClick: () => setShowPreview(!showPreview)
16243
16170
  }, /*#__PURE__*/react.createElement("span", {
16244
16171
  className: "flex-shrink-0"
16245
- }, "Preview in viewport"), /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
16172
+ }, t('Preview in viewport')), /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
16246
16173
  className: "ml-auto flex-shrink-0",
16247
16174
  checked: showPreview,
16248
16175
  onCheckedChange: checked => {
@@ -16261,7 +16188,7 @@ function WindowLevel({
16261
16188
  className: "p-1"
16262
16189
  }, windowLevelPresets.map((preset, index) => /*#__PURE__*/react.createElement(ui_next_src/* AllInOneMenu */.se.Item, {
16263
16190
  key: index,
16264
- label: preset.description,
16191
+ label: t(preset.description),
16265
16192
  secondaryLabel: `${preset.window} / ${preset.level}`,
16266
16193
  useIconSpace: false,
16267
16194
  onClick: () => {
@@ -16289,6 +16216,7 @@ function WindowLevel({
16289
16216
 
16290
16217
 
16291
16218
 
16219
+
16292
16220
  function VolumeRenderingPresetsContent({
16293
16221
  presets,
16294
16222
  viewportId,
@@ -16299,6 +16227,9 @@ function VolumeRenderingPresetsContent({
16299
16227
  } = (0,src/* useSystem */.Jg)();
16300
16228
  const [searchValue, setSearchValue] = (0,react.useState)('');
16301
16229
  const [selectedPreset, setSelectedPreset] = (0,react.useState)(null);
16230
+ const {
16231
+ t
16232
+ } = (0,es/* useTranslation */.Bd)('WindowLevelActionMenu');
16302
16233
  const handleSearchChange = (0,react.useCallback)(event => {
16303
16234
  setSearchValue(event.target.value);
16304
16235
  }, []);
@@ -16316,7 +16247,7 @@ function VolumeRenderingPresetsContent({
16316
16247
  }, /*#__PURE__*/react.createElement(ui_next_src/* PresetDialog */.MUF.PresetBody, null, /*#__PURE__*/react.createElement(ui_next_src/* PresetDialog */.MUF.PresetFilter, null, /*#__PURE__*/react.createElement(ui_next_src/* PresetDialog */.MUF.PresetSearch, {
16317
16248
  value: searchValue,
16318
16249
  onChange: handleSearchChange,
16319
- placeholder: "Search all"
16250
+ placeholder: t('Search all', 'Search all')
16320
16251
  })), /*#__PURE__*/react.createElement(ui_next_src/* PresetDialog */.MUF.PresetGrid, null, filteredPresets.map((preset, index) => /*#__PURE__*/react.createElement("div", {
16321
16252
  key: index,
16322
16253
  className: "flex cursor-pointer flex-col items-start",
@@ -16336,7 +16267,7 @@ function VolumeRenderingPresetsContent({
16336
16267
  className: "mt-4 flex-shrink-0"
16337
16268
  }, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Right, null, /*#__PURE__*/react.createElement(ui_next_src/* FooterAction */.esu.Secondary, {
16338
16269
  onClick: hide
16339
- }, "Cancel"))));
16270
+ }, t('Common:Cancel')))));
16340
16271
  }
16341
16272
  ;// ../../../extensions/cornerstone/src/components/WindowLevelActionMenu/VolumeRenderingPresets.tsx
16342
16273
 
@@ -16345,6 +16276,7 @@ function VolumeRenderingPresetsContent({
16345
16276
 
16346
16277
 
16347
16278
 
16279
+
16348
16280
  function VolumeRenderingPresets({
16349
16281
  viewportId
16350
16282
  } = {}) {
@@ -16357,11 +16289,14 @@ function VolumeRenderingPresets({
16357
16289
  const {
16358
16290
  uiDialogService
16359
16291
  } = servicesManager.services;
16292
+ const {
16293
+ t
16294
+ } = (0,es/* useTranslation */.Bd)('WindowLevelActionMenu');
16360
16295
  const onClickPresets = () => {
16361
16296
  uiDialogService.show({
16362
16297
  id: 'volume-rendering-presets',
16363
16298
  content: VolumeRenderingPresetsContent,
16364
- title: 'Rendering Presets',
16299
+ title: t('Rendering Presets'),
16365
16300
  isDraggable: true,
16366
16301
  contentProps: {
16367
16302
  presets: volumeRenderingPresets,
@@ -16370,7 +16305,7 @@ function VolumeRenderingPresets({
16370
16305
  });
16371
16306
  };
16372
16307
  return /*#__PURE__*/react.createElement(ui_next_src/* AllInOneMenu */.se.Item, {
16373
- label: "Rendering Presets",
16308
+ label: t('Rendering Presets'),
16374
16309
  icon: /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.VolumeRendering, null),
16375
16310
  rightIcon: /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.ByName, {
16376
16311
  name: "action-new-dialog"
@@ -16382,6 +16317,7 @@ function VolumeRenderingPresets({
16382
16317
 
16383
16318
 
16384
16319
 
16320
+
16385
16321
  function VolumeRenderingQuality({
16386
16322
  volumeRenderingQualityRange,
16387
16323
  viewportId
@@ -16399,6 +16335,9 @@ function VolumeRenderingQuality({
16399
16335
  step
16400
16336
  } = volumeRenderingQualityRange;
16401
16337
  const [quality, setQuality] = (0,react.useState)(null);
16338
+ const {
16339
+ t
16340
+ } = (0,es/* useTranslation */.Bd)('WindowLevelActionMenu');
16402
16341
  const onChange = (0,react.useCallback)(value => {
16403
16342
  commandsManager.runCommand('setVolumeRenderingQulaity', {
16404
16343
  viewportId,
@@ -16437,7 +16376,7 @@ function VolumeRenderingQuality({
16437
16376
  className: "flex flex-row items-center"
16438
16377
  }, /*#__PURE__*/react.createElement(ui_next_src/* Numeric */.ewR.Label, {
16439
16378
  className: "w-16"
16440
- }, "Quality"), /*#__PURE__*/react.createElement(ui_next_src/* Numeric */.ewR.SingleRange, {
16379
+ }, t('Quality')), /*#__PURE__*/react.createElement(ui_next_src/* Numeric */.ewR.SingleRange, {
16441
16380
  sliderClassName: "mx-2 flex-grow"
16442
16381
  })))));
16443
16382
  }
@@ -16445,6 +16384,7 @@ function VolumeRenderingQuality({
16445
16384
 
16446
16385
 
16447
16386
 
16387
+
16448
16388
  function VolumeShift({
16449
16389
  viewportId
16450
16390
  }) {
@@ -16466,6 +16406,9 @@ function VolumeShift({
16466
16406
  actor
16467
16407
  } = viewport.getActors()[0];
16468
16408
  const ofun = actor.getProperty().getScalarOpacity(0);
16409
+ const {
16410
+ t
16411
+ } = (0,es/* useTranslation */.Bd)('WindowLevelActionMenu');
16469
16412
  (0,react.useEffect)(() => {
16470
16413
  if (isBlocking) {
16471
16414
  return;
@@ -16505,7 +16448,7 @@ function VolumeShift({
16505
16448
  className: "flex flex-row items-center"
16506
16449
  }, /*#__PURE__*/react.createElement(ui_next_src/* Numeric */.ewR.Label, {
16507
16450
  className: "w-16"
16508
- }, "Shift"), /*#__PURE__*/react.createElement(ui_next_src/* Numeric */.ewR.SingleRange, {
16451
+ }, t('Shift')), /*#__PURE__*/react.createElement(ui_next_src/* Numeric */.ewR.SingleRange, {
16509
16452
  sliderClassName: "mx-2 flex-grow"
16510
16453
  })))));
16511
16454
  }
@@ -16513,6 +16456,7 @@ function VolumeShift({
16513
16456
 
16514
16457
 
16515
16458
 
16459
+
16516
16460
  function VolumeLighting({
16517
16461
  viewportId,
16518
16462
  hasShade
@@ -16529,6 +16473,9 @@ function VolumeLighting({
16529
16473
  diffuse: null,
16530
16474
  specular: null
16531
16475
  });
16476
+ const {
16477
+ t
16478
+ } = (0,es/* useTranslation */.Bd)('WindowLevelActionMenu');
16532
16479
 
16533
16480
  // Single callback to handle all lighting property changes
16534
16481
  const onLightingChange = (0,react.useCallback)((property, value) => {
@@ -16561,13 +16508,13 @@ function VolumeLighting({
16561
16508
  // Configuration for our lighting properties
16562
16509
  const lightingProperties = [{
16563
16510
  key: 'ambient',
16564
- label: 'Ambient'
16511
+ label: t('Ambient')
16565
16512
  }, {
16566
16513
  key: 'diffuse',
16567
- label: 'Diffuse'
16514
+ label: t('Diffuse')
16568
16515
  }, {
16569
16516
  key: 'specular',
16570
- label: 'Specular'
16517
+ label: t('Specular')
16571
16518
  }];
16572
16519
  return /*#__PURE__*/react.createElement("div", {
16573
16520
  className: "my-1 mt-2 flex flex-col space-y-2"
@@ -16596,10 +16543,14 @@ function VolumeLighting({
16596
16543
 
16597
16544
 
16598
16545
 
16546
+
16599
16547
  function VolumeShade({
16600
16548
  viewportId,
16601
16549
  onClickShade = bool => {}
16602
16550
  }) {
16551
+ const {
16552
+ t
16553
+ } = (0,es/* useTranslation */.Bd)('WindowLevelActionMenu');
16603
16554
  const {
16604
16555
  servicesManager,
16605
16556
  commandsManager
@@ -16629,7 +16580,7 @@ function VolumeShade({
16629
16580
  }, [viewportId, cornerstoneViewportService]);
16630
16581
  return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement("span", {
16631
16582
  className: "flex-grow"
16632
- }, "Shade"), /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
16583
+ }, t('Shade')), /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
16633
16584
  className: "ml-2 flex-shrink-0",
16634
16585
  key: key,
16635
16586
  checked: shade,
@@ -16648,6 +16599,7 @@ function VolumeShade({
16648
16599
 
16649
16600
 
16650
16601
 
16602
+
16651
16603
  function VolumeRenderingOptions({
16652
16604
  viewportId
16653
16605
  } = {}) {
@@ -16655,6 +16607,9 @@ function VolumeRenderingOptions({
16655
16607
  volumeRenderingQualityRange
16656
16608
  } = (0,useViewportRendering/* useViewportRendering */.e)(viewportId);
16657
16609
  const [hasShade, setShade] = (0,react.useState)(false);
16610
+ const {
16611
+ t
16612
+ } = (0,es/* useTranslation */.Bd)('WindowLevelActionMenu');
16658
16613
  return /*#__PURE__*/react.createElement(ui_next_src/* AllInOneMenu */.se.ItemPanel, null, /*#__PURE__*/react.createElement(VolumeRenderingQuality, {
16659
16614
  viewportId: viewportId,
16660
16615
  volumeRenderingQualityRange: volumeRenderingQualityRange
@@ -16664,7 +16619,7 @@ function VolumeRenderingOptions({
16664
16619
  className: "mt-2 flex h-8 !h-[20px] w-full flex-shrink-0 items-center justify-start px-2 text-base"
16665
16620
  }, /*#__PURE__*/react.createElement("div", {
16666
16621
  className: "text-muted-foreground text-sm"
16667
- }, "Lighting")), /*#__PURE__*/react.createElement("div", {
16622
+ }, t('Lighting'))), /*#__PURE__*/react.createElement("div", {
16668
16623
  className: "bg-background mt-1 mb-1 h-px w-full"
16669
16624
  }), /*#__PURE__*/react.createElement("div", {
16670
16625
  className: "hover:bg-accent flex h-8 w-full flex-shrink-0 items-center px-2 text-base hover:rounded"
@@ -16689,20 +16644,22 @@ function VolumeRenderingOptions({
16689
16644
 
16690
16645
  function WindowLevelActionMenu({
16691
16646
  viewportId,
16692
- element,
16693
16647
  align,
16694
- side
16648
+ side,
16649
+ onVisibilityChange
16695
16650
  }) {
16696
16651
  return /*#__PURE__*/react.createElement(WindowLevelActionMenuContent, {
16697
16652
  viewportId: viewportId,
16698
16653
  align: align,
16699
- side: side
16654
+ side: side,
16655
+ onVisibilityChange: onVisibilityChange
16700
16656
  });
16701
16657
  }
16702
16658
  function WindowLevelActionMenuContent({
16703
16659
  viewportId,
16704
16660
  align,
16705
- side
16661
+ side,
16662
+ onVisibilityChange
16706
16663
  }) {
16707
16664
  const {
16708
16665
  t
@@ -16723,7 +16680,8 @@ function WindowLevelActionMenuContent({
16723
16680
  isVisible: true,
16724
16681
  align: align,
16725
16682
  side: side,
16726
- backLabel: i18next/* default */.A.t('WindowLevelActionMenu:Back to Display Options')
16683
+ backLabel: i18next/* default */.A.t('WindowLevelActionMenu:Back to Display Options'),
16684
+ onVisibilityChange: onVisibilityChange
16727
16685
  }, /*#__PURE__*/react.createElement(ui_next_src/* AllInOneMenu */.se.ItemPanel, null, !is3DVolume && /*#__PURE__*/react.createElement(Colorbar, {
16728
16686
  viewportId: viewportId
16729
16687
  }), colorbarProperties?.colormaps && !is3DVolume && /*#__PURE__*/react.createElement(ui_next_src/* AllInOneMenu */.se.SubMenu, {
@@ -16758,7 +16716,6 @@ function WindowLevelActionMenuWrapper_extends() { return WindowLevelActionMenuWr
16758
16716
  function WindowLevelActionMenuWrapper(props) {
16759
16717
  const {
16760
16718
  viewportId,
16761
- element,
16762
16719
  location,
16763
16720
  isOpen = false,
16764
16721
  onOpen,
@@ -16839,9 +16796,9 @@ function WindowLevelActionMenuWrapper(props) {
16839
16796
  sideOffset: 5
16840
16797
  }, /*#__PURE__*/react.createElement(WindowLevelActionMenu, {
16841
16798
  viewportId: viewportIdToUse,
16842
- element: element,
16843
16799
  align: align,
16844
- side: side
16800
+ side: side,
16801
+ onVisibilityChange: handleOpenChange
16845
16802
  })));
16846
16803
  }
16847
16804
  ;// ../../../extensions/cornerstone/src/components/VOIManualControlMenu/VOIManualControlMenu.tsx
@@ -17481,6 +17438,7 @@ function ModalityLoadBadge({
17481
17438
 
17482
17439
 
17483
17440
 
17441
+
17484
17442
  /**
17485
17443
  * NavigationComponent provides navigation controls for viewports containing
17486
17444
  * special displaySets (SR, SEG, RTSTRUCT) to navigate between segments or measurements
@@ -17517,7 +17475,7 @@ function NavigationComponent({
17517
17475
  } = (0,hooks/* useViewportSegmentations */.Lt)({
17518
17476
  viewportId
17519
17477
  });
17520
- const hasSegmentations = segmentationsWithRepresentations.length > 0;
17478
+ const hasSegmentations = segmentationsWithRepresentations.length > 0 && segmentationsWithRepresentations.some(segmentation => segmentation?.representation?.type !== esm_enums.SegmentationRepresentations.Surface);
17521
17479
 
17522
17480
  // prefer segment navigation if available
17523
17481
  const navigationMode = hasSegmentations ? 'segment' : isSRDisplaySet ? 'measurement' : isTracked ? 'measurement' : null;
@@ -17546,7 +17504,8 @@ function NavigationComponent({
17546
17504
  if (!segmentationsWithRepresentations.length) {
17547
17505
  return;
17548
17506
  }
17549
- const segmentationId = segmentationsWithRepresentations[0].segmentation.segmentationId;
17507
+ const activeSegmentationWithRepresentation = segmentationsWithRepresentations.find(segmentation => segmentation?.representation?.active);
17508
+ const segmentationId = activeSegmentationWithRepresentation.segmentation.segmentationId;
17550
17509
  src_utils.handleSegmentChange({
17551
17510
  direction,
17552
17511
  segmentationId,
@@ -18014,9 +17973,10 @@ function AdvancedRenderingControls({
18014
17973
 
18015
17974
 
18016
17975
 
17976
+
18017
17977
  const getDisabledState = disabledText => ({
18018
17978
  disabled: true,
18019
- disabledText: disabledText ?? 'Not available on the current viewport'
17979
+ disabledText: disabledText ?? i18n_src/* default */.A.t('Buttons:Not available on the current viewport')
18020
17980
  });
18021
17981
  function getToolbarModule({
18022
17982
  servicesManager,
@@ -18349,7 +18309,7 @@ function getToolbarModule({
18349
18309
  if (supportedModalities?.length) {
18350
18310
  const hasAnySupportedModality = displaySets.some(displaySet => supportedModalities.includes(displaySet?.Modality));
18351
18311
  if (!hasAnySupportedModality) {
18352
- return getDisabledState(disabledText || 'Tool not available for this modality');
18312
+ return getDisabledState(disabledText || i18n_src/* default */.A.t('Buttons:Tool not available for this modality'));
18353
18313
  }
18354
18314
  }
18355
18315
  }
@@ -18792,9 +18752,26 @@ ToolGroupService.REGISTRATION = {
18792
18752
  ;// ../../../extensions/cornerstone/src/services/ToolGroupService/index.js
18793
18753
 
18794
18754
  /* harmony default export */ const services_ToolGroupService = (ToolGroupService);
18755
+ ;// ../../../extensions/cornerstone/src/utils/isAnyDisplaySetCommon.ts
18756
+ /**
18757
+ * Checks whether two viewports share at least one common display set.
18758
+ *
18759
+ * This method checks to see if the source and target share a display set.
18760
+ * It performs an O(n * m) comparison between the display sets of each viewport.
18761
+ * Since each viewport typically contains only a small number of display sets (≤ 5),
18762
+ * the computational cost is negligible.
18763
+ *
18764
+ * @param sourceDisplaySetUIDs - Array of displaySetInstanceUID from the source viewport.
18765
+ * @param targetDisplaySetUIDs - Array of displaySetInstanceUID from the target viewport.
18766
+ * @returns true if at least one display set is common; false otherwise.
18767
+ */
18768
+ function isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs) {
18769
+ return sourceDisplaySetUIDs.some(uid => targetDisplaySetUIDs.includes(uid));
18770
+ }
18795
18771
  ;// ../../../extensions/cornerstone/src/services/SyncGroupService/createHydrateSegmentationSynchronizer.ts
18796
18772
 
18797
18773
 
18774
+
18798
18775
  const {
18799
18776
  createSynchronizer
18800
18777
  } = dist_esm.SynchronizerManager;
@@ -18818,6 +18795,13 @@ function createHydrateSegmentationSynchronizer(synchronizerName, {
18818
18795
  });
18819
18796
  return stackImageSynchronizer;
18820
18797
  }
18798
+
18799
+ /**
18800
+ * This method will add the segmentation representation to any target viewports having:
18801
+ *
18802
+ * 1. the same FrameOfReferenceUID (FOR) as the segmentation representation, or
18803
+ * 2. a shared DisplaySet with the source viewport when no FOR is present.
18804
+ */
18821
18805
  const segmentationRepresentationModifiedCallback = async (synchronizerInstance, sourceViewport, targetViewport, sourceEvent, {
18822
18806
  servicesManager,
18823
18807
  options
@@ -18828,14 +18812,20 @@ const segmentationRepresentationModifiedCallback = async (synchronizerInstance,
18828
18812
  type: segmentationRepresentationType
18829
18813
  } = event.detail;
18830
18814
  const {
18831
- segmentationService
18815
+ segmentationService,
18816
+ cornerstoneViewportService
18832
18817
  } = servicesManager.services;
18833
18818
  const targetViewportId = targetViewport.viewportId;
18819
+ const sourceViewportId = sourceViewport.viewportId;
18834
18820
  const {
18835
18821
  viewport
18836
18822
  } = (0,esm.getEnabledElementByViewportId)(targetViewportId);
18837
- const targetFrameOfReferenceUID = viewport.getFrameOfReferenceUID();
18838
- if (!targetFrameOfReferenceUID) {
18823
+ const sourceViewportInfo = cornerstoneViewportService.getViewportInfo(sourceViewportId);
18824
+ const targetViewportInfo = cornerstoneViewportService.getViewportInfo(targetViewportId);
18825
+ const sourceDisplaySetUIDs = extractDisplaySetUIDs(sourceViewportInfo);
18826
+ const targetDisplaySetUIDs = extractDisplaySetUIDs(targetViewportInfo);
18827
+ const sharedDisplaySetExists = isAnyDisplaySetCommon(sourceDisplaySetUIDs, targetDisplaySetUIDs);
18828
+ if (!sharedDisplaySetExists && !viewport.getFrameOfReferenceUID()) {
18839
18829
  return;
18840
18830
  }
18841
18831
  const targetViewportRepresentation = segmentationService.getSegmentationRepresentations(targetViewportId, {
@@ -18851,10 +18841,17 @@ const segmentationRepresentationModifiedCallback = async (synchronizerInstance,
18851
18841
  segmentationId,
18852
18842
  type,
18853
18843
  config: {
18854
- blendMode: viewport.getBlendMode() === 1 ? BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
18844
+ blendMode: viewport?.getBlendMode?.() === 1 ? BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
18855
18845
  }
18856
18846
  });
18857
18847
  };
18848
+
18849
+ /**
18850
+ * Extracts the displaySetInstanceUIDs from a viewportInfo.
18851
+ */
18852
+ function extractDisplaySetUIDs(viewportInfo) {
18853
+ return viewportInfo.getViewportData().data.map(ds => ds.displaySetInstanceUID);
18854
+ }
18858
18855
  ;// ../../../extensions/cornerstone/src/services/SyncGroupService/SyncGroupService.ts
18859
18856
  var _SyncGroupService;
18860
18857
 
@@ -19138,6 +19135,9 @@ var _SegmentationService;
19138
19135
 
19139
19136
 
19140
19137
 
19138
+ const {
19139
+ DefaultHistoryMemo: SegmentationService_DefaultHistoryMemo
19140
+ } = esm.utilities.HistoryMemo;
19141
19141
  const {
19142
19142
  Labelmap: LABELMAP,
19143
19143
  Contour: CONTOUR,
@@ -19898,11 +19898,69 @@ class SegmentationService extends src/* PubSubService */.Rc {
19898
19898
  });
19899
19899
  }
19900
19900
 
19901
+ /**
19902
+ * Creates a memo that records the current state of a segment (segmentationId/segmentIndex)
19903
+ * so that undo can restore it via addSegment and redo can call removeSegment again
19904
+ * without recording history.
19905
+ *
19906
+ * @param segmentationId - The ID of the segmentation.
19907
+ * @param segmentIndex - The index of the segment (must still exist when called).
19908
+ * @param _options - Reserved (e.g. deleting) for future use.
19909
+ * @returns A Memo with restoreMemo(undo): undo => addSegment, redo => removeSegment (skipRecordingHistory).
19910
+ */
19911
+ createSegmentIndexMemo(segmentationId, segmentIndex, _options) {
19912
+ const csSegmentation = this.getCornerstoneSegmentation(segmentationId);
19913
+ const segment = csSegmentation?.segments?.[segmentIndex];
19914
+ if (!segment) {
19915
+ return null;
19916
+ }
19917
+ let color;
19918
+ let visibility;
19919
+ const viewportIds = this.getViewportIdsWithSegmentation(segmentationId);
19920
+ if (viewportIds.length > 0) {
19921
+ const firstViewportId = viewportIds[0];
19922
+ const representations = this.getSegmentationRepresentations(firstViewportId, {
19923
+ segmentationId
19924
+ });
19925
+ const repType = representations[0]?.type ?? LABELMAP;
19926
+ color = this.getSegmentColor(firstViewportId, segmentationId, segmentIndex);
19927
+ visibility = dist_esm.segmentation.config.visibility.getSegmentIndexVisibility(firstViewportId, {
19928
+ segmentationId,
19929
+ type: repType
19930
+ }, segmentIndex);
19931
+ }
19932
+ const segmentState = {
19933
+ segmentIndex,
19934
+ label: segment.label,
19935
+ isLocked: segment.locked,
19936
+ active: segment.active,
19937
+ color,
19938
+ visibility
19939
+ };
19940
+ const service = this;
19941
+ const memo = {
19942
+ id: esm.utilities.uuidv4(),
19943
+ operationType: 'segmentIndex',
19944
+ restoreMemo(undo) {
19945
+ if (undo === true) {
19946
+ service.addSegment(segmentationId, segmentState);
19947
+ } else {
19948
+ // Redo: remove the segment via cornerstone without recording history
19949
+ dist_esm.segmentation.removeSegment(segmentationId, segmentIndex, {
19950
+ recordHistory: false
19951
+ });
19952
+ }
19953
+ }
19954
+ };
19955
+ return memo;
19956
+ }
19957
+
19901
19958
  /**
19902
19959
  * Removes a segment from a segmentation and updates the active segment index if necessary.
19903
19960
  *
19904
19961
  * @param segmentationId - The ID of the segmentation containing the segment to remove.
19905
19962
  * @param segmentIndex - The index of the segment to remove.
19963
+ * @param options - Optional. skipRecordingHistory: if true, do not push undo memo (used when redoing).
19906
19964
  *
19907
19965
  * @remarks
19908
19966
  * This method performs the following actions:
@@ -19911,8 +19969,23 @@ class SegmentationService extends src/* PubSubService */.Rc {
19911
19969
  * 3. If the removed segment was the active segment, it updates the active segment index.
19912
19970
  *
19913
19971
  */
19914
- removeSegment(segmentationId, segmentIndex) {
19915
- dist_esm.segmentation.removeSegment(segmentationId, segmentIndex);
19972
+ removeSegment(segmentationId, segmentIndex, options) {
19973
+ let memo;
19974
+ if (!options?.skipRecordingHistory) {
19975
+ memo = this.createSegmentIndexMemo(segmentationId, segmentIndex, {
19976
+ deleting: true
19977
+ });
19978
+ SegmentationService_DefaultHistoryMemo.startGroupRecording();
19979
+ dist_esm.segmentation.removeSegment(segmentationId, segmentIndex, {
19980
+ recordHistory: true
19981
+ });
19982
+ SegmentationService_DefaultHistoryMemo.push(memo);
19983
+ SegmentationService_DefaultHistoryMemo.endGroupRecording();
19984
+ } else {
19985
+ dist_esm.segmentation.removeSegment(segmentationId, segmentIndex, {
19986
+ recordHistory: false
19987
+ });
19988
+ }
19916
19989
  }
19917
19990
  setSegmentVisibility(viewportId, segmentationId, segmentIndex, isVisible, type) {
19918
19991
  this._setSegmentVisibility(viewportId, segmentationId, segmentIndex, isVisible, type);
@@ -20128,15 +20201,111 @@ class SegmentationService extends src/* PubSubService */.Rc {
20128
20201
  removeSegmentationRepresentations(viewportId, specifier = {}) {
20129
20202
  dist_esm.segmentation.removeSegmentationRepresentations(viewportId, specifier);
20130
20203
  }
20131
- jumpToSegmentCenter(segmentationId, segmentIndex, viewportId, highlightAlpha = 0.9, highlightSegment = true, animationLength = 750, highlightHideOthers = false, animationFunctionType = EasingFunctionEnum.EASE_IN_OUT) {
20132
- const center = this._getSegmentCenter(segmentationId, segmentIndex);
20133
- if (!center) {
20204
+
20205
+ /**
20206
+ * Jumps to the next slice that contains the specified segment in the viewport.
20207
+ * For labelmaps, it jumps to the segment center. For contours, it cycles through
20208
+ * all slices that contain contour data for the segment.
20209
+ *
20210
+ * @param segmentationId - The ID of the segmentation
20211
+ * @param segmentIndex - The index of the segment to jump to
20212
+ * @param viewportId - Optional viewport ID. If not provided, applies to all viewports with this segmentation
20213
+ * @param highlightAlpha - Alpha value for highlighting (0-1)
20214
+ * @param highlightSegment - Whether to highlight the segment after jumping
20215
+ * @param animationLength - Length of highlight animation in milliseconds
20216
+ * @param highlightHideOthers - Whether to hide other segments during highlight
20217
+ * @param animationFunctionType - The easing function to use for animation
20218
+ */
20219
+ jumpToSegmentNext(segmentationId, segmentIndex, forViewportId, direction = 1, highlightAlpha = 0.9, highlightSegment = true, animationLength = 750, highlightHideOthers = false, animationFunctionType = EasingFunctionEnum.EASE_IN_OUT) {
20220
+ const viewportIds = forViewportId ? [forViewportId] : this.getViewportIdsWithSegmentation(segmentationId);
20221
+ viewportIds.forEach(viewportId => {
20222
+ const representations = this.getSegmentationRepresentations(viewportId, {
20223
+ segmentationId
20224
+ });
20225
+ if (!representations || representations.length === 0) {
20226
+ return;
20227
+ }
20228
+ const representation = representations[0];
20229
+ const {
20230
+ type
20231
+ } = representation;
20232
+
20233
+ // For contours, check if we have a segment center.
20234
+ const center = type === CONTOUR ? this._getSegmentCenter(segmentationId, segmentIndex) : undefined;
20235
+ const canUseSegmentCenter = type !== CONTOUR || !!center;
20236
+ if (canUseSegmentCenter) {
20237
+ this.jumpToSegmentCenter(segmentationId, segmentIndex, viewportId, highlightAlpha, highlightSegment, animationLength, highlightHideOthers, animationFunctionType, center);
20238
+ return;
20239
+ }
20240
+ const {
20241
+ viewport
20242
+ } = (0,esm.getEnabledElementByViewportId)(viewportId);
20243
+ if (!viewport) {
20244
+ return;
20245
+ }
20246
+ const viewRefs = this._getContourViewReferences(segmentationId, viewport, segmentIndex);
20247
+ if (!viewRefs) {
20248
+ return;
20249
+ }
20250
+
20251
+ // Get the current slice index
20252
+ const currentSliceIndex = viewport.getCurrentImageIdIndex();
20253
+ let nearestSliceIndex = null;
20254
+ let loopSliceIndex = null;
20255
+ for (const [sliceIndex] of viewRefs.entries()) {
20256
+ // Track loop index for wraparound (smallest for forward, largest for backward)
20257
+ if (direction > 0) {
20258
+ if (loopSliceIndex === null || sliceIndex < loopSliceIndex) {
20259
+ loopSliceIndex = sliceIndex;
20260
+ }
20261
+ } else {
20262
+ if (loopSliceIndex === null || sliceIndex > loopSliceIndex) {
20263
+ loopSliceIndex = sliceIndex;
20264
+ }
20265
+ }
20266
+ if (direction > 0) {
20267
+ // Forward direction: find nearest slice after current
20268
+ if (sliceIndex <= currentSliceIndex) {
20269
+ continue;
20270
+ }
20271
+ if (nearestSliceIndex === null || sliceIndex < nearestSliceIndex) {
20272
+ nearestSliceIndex = sliceIndex;
20273
+ }
20274
+ } else {
20275
+ // Backward direction: find nearest slice before current
20276
+ if (sliceIndex >= currentSliceIndex) {
20277
+ continue;
20278
+ }
20279
+ if (nearestSliceIndex === null || sliceIndex > nearestSliceIndex) {
20280
+ nearestSliceIndex = sliceIndex;
20281
+ }
20282
+ }
20283
+ }
20284
+
20285
+ // Wraparound: if no slice found in direction, use loop index
20286
+ nearestSliceIndex = nearestSliceIndex ?? loopSliceIndex;
20287
+ if (nearestSliceIndex === null) {
20288
+ return;
20289
+ }
20290
+ const viewRef = viewRefs.get(nearestSliceIndex);
20291
+ viewport.setViewReference(viewRef);
20292
+ viewport.render();
20293
+ });
20294
+ }
20295
+
20296
+ /**
20297
+ * Jumps the viewport to the center of hte given segment.
20298
+ * Only works for labelmaps, and may result in not showing any contours.
20299
+ */
20300
+ jumpToSegmentCenter(segmentationId, segmentIndex, viewportId, highlightAlpha = 0.9, highlightSegment = true, animationLength = 750, highlightHideOthers = false, animationFunctionType = EasingFunctionEnum.EASE_IN_OUT, center) {
20301
+ const resolvedCenter = center ?? this._getSegmentCenter(segmentationId, segmentIndex);
20302
+ if (!resolvedCenter) {
20134
20303
  console.warn('No center found for segmentation', segmentationId, segmentIndex);
20135
20304
  return;
20136
20305
  }
20137
20306
  const {
20138
20307
  world
20139
- } = center;
20308
+ } = resolvedCenter;
20140
20309
 
20141
20310
  // need to find which viewports are displaying the segmentation
20142
20311
  const viewportIds = viewportId ? [viewportId] : this.getViewportIdsWithSegmentation(segmentationId);
@@ -20144,6 +20313,9 @@ class SegmentationService extends src/* PubSubService */.Rc {
20144
20313
  const {
20145
20314
  viewport
20146
20315
  } = (0,esm.getEnabledElementByViewportId)(viewportId);
20316
+ if (!viewport?.jumpToWorld) {
20317
+ return;
20318
+ }
20147
20319
  viewport.jumpToWorld(world);
20148
20320
  highlightSegment && this.highlightSegment(segmentationId, segmentIndex, viewportId, highlightAlpha, animationLength, highlightHideOthers, animationFunctionType);
20149
20321
  });
@@ -20530,6 +20702,54 @@ class SegmentationService extends src/* PubSubService */.Rc {
20530
20702
  }
20531
20703
  }]);
20532
20704
  }
20705
+ /**
20706
+ * Gets slice indices for contour segmentations by checking view references from annotation metadata
20707
+ * @private
20708
+ */
20709
+ _getContourViewReferences(segmentationId, viewport, segmentIndex) {
20710
+ const segmentation = dist_esm.segmentation.state.getSegmentation(segmentationId);
20711
+ const contourData = segmentation.representationData[CONTOUR];
20712
+ if (!contourData || !contourData.annotationUIDsMap) {
20713
+ return;
20714
+ }
20715
+ const viewReferences = new Map();
20716
+ // Iterate through the annotationUIDsMap
20717
+ contourData.annotationUIDsMap.forEach((annotationUIDs, currentSegmentIndex) => {
20718
+ // Filter by segment index if specified
20719
+ if (segmentIndex !== undefined && currentSegmentIndex !== segmentIndex) {
20720
+ return;
20721
+ }
20722
+ // Process each annotation UID
20723
+ annotationUIDs.forEach(annotationUID => {
20724
+ const annotation = dist_esm.annotation.state.getAnnotation(annotationUID);
20725
+ if (!annotation?.metadata) {
20726
+ return;
20727
+ }
20728
+ const {
20729
+ metadata
20730
+ } = annotation;
20731
+ // Check if the viewport can view this annotation's view reference with navigation
20732
+ const isViewable = viewport.isReferenceViewable(metadata, {
20733
+ withNavigation: true
20734
+ });
20735
+ if (!isViewable) {
20736
+ return;
20737
+ }
20738
+ const {
20739
+ sliceIndex
20740
+ } = metadata;
20741
+ if (sliceIndex === undefined) {
20742
+ console.warn("Can't find slice index:", metadata);
20743
+ return;
20744
+ }
20745
+ viewReferences.set(sliceIndex, metadata);
20746
+ });
20747
+ });
20748
+ if (viewReferences.size === 0) {
20749
+ return;
20750
+ }
20751
+ return viewReferences;
20752
+ }
20533
20753
  }
20534
20754
  _SegmentationService = SegmentationService;
20535
20755
  SegmentationService.REGISTRATION = {
@@ -21153,6 +21373,8 @@ var _CornerstoneViewportService;
21153
21373
 
21154
21374
 
21155
21375
 
21376
+
21377
+
21156
21378
  const CornerstoneViewportService_EVENTS = {
21157
21379
  VIEWPORT_DATA_CHANGED: 'event::cornerstoneViewportService:viewportDataChanged',
21158
21380
  VIEWPORT_VOLUMES_CHANGED: 'event::cornerstoneViewportService:viewportVolumesChanged'
@@ -21596,8 +21818,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21596
21818
  * viewport to display the image in where it matches, in order:
21597
21819
  * * Active viewport that can be navigated to the given image without orientation change
21598
21820
  * * Other viewport that can be navigated to the given image without orientation change
21599
- * * Active viewport that can change orientation to display the image
21600
- * * Other viewport that can change orientation to display the image
21821
+ * * Best-aligned viewport that can display the image with an orientation change
21601
21822
  *
21602
21823
  * It returns `null` otherwise, indicating that a viewport needs display set/type
21603
21824
  * changes in order to display the image.
@@ -21620,9 +21841,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21620
21841
  if (!activeViewport) {
21621
21842
  console.warn('No active viewport found for', activeViewportId);
21622
21843
  }
21623
- if (activeViewport?.isReferenceViewable(metadata, {
21624
- withNavigation: true
21625
- })) {
21844
+ if (activeViewport?.isReferenceViewable(metadata, WITH_NAVIGATION)) {
21626
21845
  return activeViewportId;
21627
21846
  }
21628
21847
 
@@ -21630,29 +21849,21 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21630
21849
  // without considering orientation changes.
21631
21850
  for (const id of this.viewportsById.keys()) {
21632
21851
  const viewport = this.getCornerstoneViewport(id);
21633
- if (viewport?.isReferenceViewable(metadata, {
21634
- withNavigation: true
21635
- })) {
21852
+ if (viewport?.isReferenceViewable(metadata, WITH_NAVIGATION)) {
21636
21853
  return id;
21637
21854
  }
21638
21855
  }
21639
21856
 
21640
- // No viewport is in the right display set/orientation to show this, so see if
21641
- // the active viewport could change orientations to show this
21642
- if (activeViewport?.isReferenceViewable(metadata, {
21643
- withNavigation: true,
21644
- withOrientation: true
21645
- })) {
21646
- return activeViewportId;
21647
- }
21857
+ // Compute view-plane alignment scores for all viewports to prefer the one
21858
+ // requiring the least orientation change when navigation-only is not possible.
21859
+ const viewportAlignmentData = this.getViewportAlignmentData(metadata);
21648
21860
 
21649
21861
  // See if any viewport could show this with an orientation change
21650
- for (const id of this.viewportsById.keys()) {
21862
+ for (const {
21863
+ viewportId: id
21864
+ } of viewportAlignmentData) {
21651
21865
  const viewport = this.getCornerstoneViewport(id);
21652
- if (viewport?.isReferenceViewable(metadata, {
21653
- withNavigation: true,
21654
- withOrientation: true
21655
- })) {
21866
+ if (viewport?.isReferenceViewable(metadata, WITH_ORIENTATION)) {
21656
21867
  return id;
21657
21868
  }
21658
21869
  }
@@ -21662,24 +21873,51 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21662
21873
  }
21663
21874
 
21664
21875
  /**
21665
- * Figures out which viewport to update when the viewport type needs to change.
21666
- * This may not be the active viewport if there is already a viewport showing
21667
- * the display set, but in the wrong orientation.
21668
- *
21669
- * The viewport will need to update the viewport type and/or display set to
21670
- * display the resulting data.
21671
- *
21672
- * The first choice will be a viewport already showing the correct display set,
21673
- * but showing it as a stack.
21876
+ * Given a metadata instance containing a planeRestriction, returns the
21877
+ * ordered list of best orientation match viewport ids.
21674
21878
  *
21675
- * Second choice is to see if there is a viewport already showing the right
21676
- * orientation for the image, but the wrong display set. This fixes the
21677
- * case where the user is in MPR and a viewport other than active should be
21678
- * the one to change to display the iamge.
21679
- *
21680
- * Final choice is to use the provide activeViewportId. This will cover
21681
- * changes to/from video and wsi viewports and other cases where no
21682
- * viewport is really even close to being able to display the measurement.
21879
+ * This uses the planeRestriction preferentially as that one is more reliably
21880
+ * filled than the viewport normal since it is created from data points on
21881
+ * rehydration.
21882
+ */
21883
+ getViewportAlignmentData(metadata) {
21884
+ const viewportAlignmentData = [];
21885
+ const {
21886
+ viewPlaneNormal: refViewPlaneNormal,
21887
+ planeRestriction
21888
+ } = metadata;
21889
+ const inPlaneVector1 = planeRestriction?.inPlaneVector1;
21890
+ const inPlaneVector2 = planeRestriction?.inPlaneVector2;
21891
+ for (const id of this.viewportsById.keys()) {
21892
+ const viewport = this.getCornerstoneViewport(id);
21893
+ const {
21894
+ viewPlaneNormal
21895
+ } = viewport.getCamera();
21896
+ if (!viewPlaneNormal) {
21897
+ continue;
21898
+ }
21899
+ let alignmentScore = 0;
21900
+ if (inPlaneVector1 || inPlaneVector2) {
21901
+ const inPlane1Score = inPlaneVector1 ? -Math.abs(gl_matrix_esm/* vec3.dot */.eR.dot(viewPlaneNormal, inPlaneVector1)) : 0;
21902
+ const inPlane2Score = inPlaneVector2 ? -Math.abs(gl_matrix_esm/* vec3.dot */.eR.dot(viewPlaneNormal, inPlaneVector2)) : 0;
21903
+ alignmentScore = inPlane1Score + inPlane2Score;
21904
+ } else if (refViewPlaneNormal) {
21905
+ alignmentScore = Math.abs(gl_matrix_esm/* vec3.dot */.eR.dot(viewPlaneNormal, refViewPlaneNormal));
21906
+ }
21907
+ viewportAlignmentData.push({
21908
+ viewportId: id,
21909
+ alignmentScore
21910
+ });
21911
+ }
21912
+
21913
+ // Try best-aligned viewports first
21914
+ viewportAlignmentData.sort((a, b) => b.alignmentScore - a.alignmentScore);
21915
+ return viewportAlignmentData;
21916
+ }
21917
+
21918
+ /**
21919
+ * Figures out which viewport to update when the viewport type needs to change.
21920
+ * Orchestrates the search strategies in order of preference.
21683
21921
  */
21684
21922
  findUpdateableViewportConfiguration(activeViewportId, measurement) {
21685
21923
  const {
@@ -21687,47 +21925,98 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21687
21925
  displaySetInstanceUID
21688
21926
  } = measurement;
21689
21927
  const {
21690
- volumeId,
21691
- referencedImageId
21692
- } = metadata;
21693
- const {
21694
- displaySetService,
21695
- viewportGridService
21928
+ displaySetService
21696
21929
  } = this.servicesManager.services;
21697
21930
  const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
21931
+
21932
+ // 1. Determine the target Viewport Type (Stack vs Volume)
21933
+ const viewportType = this.determineTargetViewportType(displaySet, metadata);
21934
+
21935
+ // 2. Strategy: Find viewport already showing this volume
21936
+ const volumeMatch = this.findViewportShowingVolume(metadata, displaySetInstanceUID, viewportType);
21937
+ if (volumeMatch) {
21938
+ return volumeMatch;
21939
+ }
21940
+
21941
+ // 3. Strategy: Find viewport with compatible orientation (even if different display set)
21942
+ const compatibleMatch = this.findViewportConvertibleToVolume(metadata, displaySetInstanceUID, viewportType);
21943
+ if (compatibleMatch) {
21944
+ return compatibleMatch;
21945
+ }
21946
+
21947
+ // 4. Strategy: Find viewport with matching orientation via IOP
21948
+ const orientationMatch = this.findViewportWithMatchingOrientation(metadata, displaySetInstanceUID, viewportType);
21949
+ if (orientationMatch) {
21950
+ return orientationMatch;
21951
+ }
21952
+
21953
+ // 5. Fallback: Use the active viewport
21954
+ return {
21955
+ viewportId: activeViewportId,
21956
+ displaySetInstanceUID,
21957
+ viewportOptions: {
21958
+ viewportType
21959
+ }
21960
+ };
21961
+ }
21962
+
21963
+ /**
21964
+ * Determines if the viewport should be what is specified in
21965
+ * the viewportType of the display set, or stack if the display
21966
+ * set isn't reconstructable and there is a referenced image id, otherwise
21967
+ * volume.
21968
+ *
21969
+ * Expect there to be more rules in the future for different types of annotations/settings
21970
+ * such as 3d annotations.
21971
+ */
21972
+ determineTargetViewportType(displaySet, metadata) {
21698
21973
  let {
21699
21974
  viewportType
21700
21975
  } = displaySet;
21701
21976
  if (!viewportType) {
21702
- if (referencedImageId && !displaySet.isReconstructable) {
21977
+ if (metadata.referencedImageId && !displaySet.isReconstructable) {
21703
21978
  viewportType = esm.Enums.ViewportType.STACK;
21704
- } else if (volumeId) {
21979
+ } else if (metadata.volumeId) {
21705
21980
  viewportType = 'volume';
21706
21981
  }
21707
21982
  }
21983
+ return viewportType;
21984
+ }
21708
21985
 
21709
- // Find viewports that could be updated to be volumes to show this view
21710
- // That prefers a viewport already showing the right display set.
21711
- if (volumeId) {
21712
- for (const id of this.viewportsById.keys()) {
21713
- const viewport = this.getCornerstoneViewport(id);
21714
- if (viewport?.isReferenceViewable(metadata, {
21715
- asVolume: true,
21716
- withNavigation: true
21717
- })) {
21718
- return {
21719
- viewportId: id,
21720
- displaySetInstanceUID,
21721
- viewportOptions: {
21722
- viewportType
21723
- }
21724
- };
21725
- }
21986
+ /**
21987
+ * Find viewports that could be updated to be volumes to show this view.
21988
+ * Prefers a viewport already showing the right display set.
21989
+ */
21990
+ findViewportShowingVolume(metadata, displaySetInstanceUID, viewportType) {
21991
+ if (!metadata.volumeId) {
21992
+ return null;
21993
+ }
21994
+ for (const id of this.viewportsById.keys()) {
21995
+ const viewport = this.getCornerstoneViewport(id);
21996
+ if (viewport?.isReferenceViewable(metadata, {
21997
+ asVolume: true,
21998
+ withNavigation: true
21999
+ })) {
22000
+ return {
22001
+ viewportId: id,
22002
+ displaySetInstanceUID,
22003
+ viewportOptions: {
22004
+ viewportType
22005
+ }
22006
+ };
21726
22007
  }
21727
22008
  }
22009
+ return null;
22010
+ }
21728
22011
 
21729
- // Find a viewport in the correct orientation showing a different display set
21730
- // which could be used to display the annotation.
22012
+ /**
22013
+ * Find a viewport that could be converted to a volume to show this annotation,
22014
+ * already showing the right display set.
22015
+ */
22016
+ findViewportConvertibleToVolume(metadata, displaySetInstanceUID, viewportType) {
22017
+ const {
22018
+ viewportGridService
22019
+ } = this.servicesManager.services;
21731
22020
  const altMetadata = {
21732
22021
  ...metadata,
21733
22022
  volumeId: null,
@@ -21739,7 +22028,7 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21739
22028
  if (!viewportDisplaySetUID || !viewport) {
21740
22029
  continue;
21741
22030
  }
21742
- if (volumeId) {
22031
+ if (metadata.volumeId) {
21743
22032
  altMetadata.volumeId = viewportDisplaySetUID;
21744
22033
  }
21745
22034
  altMetadata.FrameOfReferenceUID = this._getFrameOfReferenceUID(viewportDisplaySetUID);
@@ -21756,15 +22045,24 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
21756
22045
  };
21757
22046
  }
21758
22047
  }
22048
+ return null;
22049
+ }
21759
22050
 
21760
- // Just display in the active viewport
21761
- return {
21762
- viewportId: activeViewportId,
21763
- displaySetInstanceUID,
21764
- viewportOptions: {
21765
- viewportType
21766
- }
21767
- };
22051
+ /**
22052
+ * Find a viewport with the closest orientation but on a different display set.
22053
+ */
22054
+ findViewportWithMatchingOrientation(metadata, displaySetInstanceUID, viewportType) {
22055
+ const viewportAlignmentData = this.getViewportAlignmentData(metadata);
22056
+ if (viewportAlignmentData?.length) {
22057
+ return {
22058
+ ...viewportAlignmentData[0],
22059
+ displaySetInstanceUID,
22060
+ viewportOptions: {
22061
+ viewportType
22062
+ }
22063
+ };
22064
+ }
22065
+ return null;
21768
22066
  }
21769
22067
 
21770
22068
  /**
@@ -22161,7 +22459,10 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22161
22459
  segmentationService.addSegmentationRepresentation(viewport.id, {
22162
22460
  segmentationId,
22163
22461
  predecessorImageId,
22164
- type: representationType
22462
+ type: representationType,
22463
+ config: {
22464
+ blendMode: viewport?.getBlendMode?.() === 1 ? dist_esm_enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
22465
+ }
22165
22466
  });
22166
22467
 
22167
22468
  // store the segmentation presentation id in the viewport info
@@ -22390,7 +22691,10 @@ class CornerstoneViewportService extends src/* PubSubService */.Rc {
22390
22691
  if (hydrated) {
22391
22692
  segmentationService.addSegmentationRepresentation(viewport.id, {
22392
22693
  segmentationId,
22393
- type: representationType
22694
+ type: representationType,
22695
+ config: {
22696
+ blendMode: viewport?.getBlendMode?.() === 1 ? dist_esm_enums.BlendModes.LABELMAP_EDGE_PROJECTION_BLEND : undefined
22697
+ }
22394
22698
  });
22395
22699
  }
22396
22700
  });
@@ -23215,7 +23519,7 @@ const hasExportableContourData = contour => {
23215
23519
 
23216
23520
  function PanelSegmentation({
23217
23521
  children,
23218
- segmentationRepresentationType
23522
+ segmentationRepresentationTypes
23219
23523
  }) {
23220
23524
  const {
23221
23525
  commandsManager,
@@ -23236,8 +23540,8 @@ function PanelSegmentation({
23236
23540
  [esm_enums.SegmentationRepresentations.Contour]: toolbarService.sections.contourSegmentationUtilities
23237
23541
  };
23238
23542
  const selectedSegmentationsForViewportMap = useSelectedSegmentationsForViewportStore(store => store.selectedSegmentationsForViewport[activeViewportId]);
23239
- const selectedSegmentationIdForType = segmentationRepresentationType ? selectedSegmentationsForViewportMap?.get(segmentationRepresentationType) : segmentationService?.getActiveSegmentation(activeViewportId)?.segmentationId;
23240
- const buttonSection = utilitiesSectionMap[segmentationRepresentationType];
23543
+ const selectedSegmentationIdForType = segmentationRepresentationTypes ? segmentationRepresentationTypes.reduce((selectedSegmentation, type) => selectedSegmentation || (selectedSegmentationsForViewportMap?.has(type) ? selectedSegmentationsForViewportMap?.get(type) : undefined), undefined) : segmentationService?.getActiveSegmentation(activeViewportId)?.segmentationId;
23544
+ const buttonSection = segmentationRepresentationTypes?.[0] ? utilitiesSectionMap[segmentationRepresentationTypes[0]] : undefined;
23241
23545
  const {
23242
23546
  activeToolOptions: activeUtilityOptions
23243
23547
  } = (0,src/* useActiveToolOptions */.KP)({
@@ -23326,7 +23630,7 @@ function PanelSegmentation({
23326
23630
  segmentIndex
23327
23631
  });
23328
23632
  },
23329
- onSegmentCopy: segmentationRepresentationType === esm_enums.SegmentationRepresentations.Contour ? (segmentationId, segmentIndex) => {
23633
+ onSegmentCopy: segmentationRepresentationTypes?.[0] === esm_enums.SegmentationRepresentations.Contour ? (segmentationId, segmentIndex) => {
23330
23634
  commandsManager.run('copyContourSegment', {
23331
23635
  sourceSegmentInfo: {
23332
23636
  segmentationId,
@@ -23489,13 +23793,13 @@ function PanelSegmentation({
23489
23793
  disabled,
23490
23794
  data: segmentationsWithRepresentations,
23491
23795
  mode: segmentationTableMode,
23492
- title: `${segmentationRepresentationType ? `${segmentationRepresentationType} ` : ''}Segmentations`,
23796
+ title: `${segmentationRepresentationTypes?.[0] ? `${segmentationRepresentationTypes[0]} ` : ''}Segmentations`,
23493
23797
  exportOptions,
23494
23798
  disableEditing,
23495
23799
  onSegmentationAdd,
23496
23800
  showAddSegment,
23497
23801
  renderInactiveSegmentations: handlers.getRenderInactiveSegmentations(),
23498
- segmentationRepresentationType,
23802
+ segmentationRepresentationTypes,
23499
23803
  selectedSegmentationIdForType,
23500
23804
  ...handlers
23501
23805
  };
@@ -23556,16 +23860,17 @@ const workerFn = () => {
23556
23860
  name: 'histogram-worker' // name used by the browser to name the worker
23557
23861
  });
23558
23862
  };
23863
+
23864
+ // Register worker once at module load time
23865
+ workerManager.registerWorker('histogram-worker', workerFn, WorkerOptions);
23559
23866
  const getViewportVolumeHistogram = async (viewport, volume, options) => {
23560
- workerManager.registerWorker('histogram-worker', workerFn, WorkerOptions);
23561
23867
  const volumeImageData = viewport.getImageData(volume.volumeId);
23562
23868
  if (!volumeImageData) {
23563
23869
  return undefined;
23564
23870
  }
23565
23871
  let scalarData = volume.scalarData;
23566
23872
  if (volume.numTimePoints > 1) {
23567
- const targetTimePoint = volume.numTimePoints - 1; // or any other time point you need
23568
- scalarData = volume.voxelManager.getTimePointScalarData(targetTimePoint);
23873
+ scalarData = volume.voxelManager.getDimensionGroupScalarData(volume.numTimePoints);
23569
23874
  } else {
23570
23875
  scalarData = volume.voxelManager.getCompleteScalarDataArray();
23571
23876
  }
@@ -23614,6 +23919,9 @@ const getViewportVolumeHistogram = async (viewport, volume, options) => {
23614
23919
  * Gets node opacity from volume actor
23615
23920
  */
23616
23921
  const getNodeOpacity = (volumeActor, nodeIndex) => {
23922
+ if (!volumeActor) {
23923
+ return undefined;
23924
+ }
23617
23925
  const volumeOpacity = volumeActor.getProperty().getScalarOpacity(0);
23618
23926
  const nodeValue = [];
23619
23927
  volumeOpacity.getNodeValue(nodeIndex, nodeValue);
@@ -23624,6 +23932,9 @@ const getNodeOpacity = (volumeActor, nodeIndex) => {
23624
23932
  * Checks if the opacity applied to the PET volume follows a specific pattern
23625
23933
  */
23626
23934
  const isPetVolumeWithDefaultOpacity = (volumeId, volumeActor) => {
23935
+ if (!volumeActor) {
23936
+ return false;
23937
+ }
23627
23938
  const volume = esm.cache.getVolume(volumeId);
23628
23939
  if (!volume || volume.metadata.Modality !== 'PT') {
23629
23940
  return false;
@@ -23655,6 +23966,9 @@ const isPetVolumeWithDefaultOpacity = (volumeId, volumeActor) => {
23655
23966
  * Checks if volume has constant opacity
23656
23967
  */
23657
23968
  const isVolumeWithConstantOpacity = volumeActor => {
23969
+ if (!volumeActor) {
23970
+ return false;
23971
+ }
23658
23972
  const volumeOpacity = volumeActor.getProperty().getScalarOpacity(0);
23659
23973
  const opacitySize = volumeOpacity.getSize();
23660
23974
  const firstNodeValue = [];
@@ -23681,7 +23995,7 @@ const getWindowLevelsData = async (viewport, viewportInfo, getVolumeOpacity) =>
23681
23995
  const viewportProperties = viewport.getProperties();
23682
23996
  const {
23683
23997
  voiRange
23684
- } = viewportProperties;
23998
+ } = viewportProperties || {};
23685
23999
  const viewportVoi = voiRange ? {
23686
24000
  windowWidth: voiRange.upper - voiRange.lower,
23687
24001
  windowCenter: voiRange.lower + (voiRange.upper - voiRange.lower) / 2
@@ -24280,6 +24594,7 @@ function StudySummaryFromMetadata(props) {
24280
24594
 
24281
24595
 
24282
24596
 
24597
+
24283
24598
  function StudyMeasurementsActions({
24284
24599
  items,
24285
24600
  StudyInstanceUID,
@@ -24289,6 +24604,9 @@ function StudyMeasurementsActions({
24289
24604
  const {
24290
24605
  commandsManager
24291
24606
  } = (0,src/* useSystem */.Jg)();
24607
+ const {
24608
+ t
24609
+ } = (0,es/* useTranslation */.Bd)('MeasurementTable');
24292
24610
  const disabled = !items?.length;
24293
24611
  if (disabled) {
24294
24612
  return null;
@@ -24329,7 +24647,7 @@ function StudyMeasurementsActions({
24329
24647
  measurementFilter
24330
24648
  });
24331
24649
  }
24332
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Add, null), "Create SR"), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
24650
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Add, null), t('Create SR')), /*#__PURE__*/react.createElement(ui_next_src/* Button */.$nd, {
24333
24651
  size: "sm",
24334
24652
  variant: "ghost",
24335
24653
  className: "pl-0.5",
@@ -24343,7 +24661,7 @@ function StudyMeasurementsActions({
24343
24661
  measurementFilter
24344
24662
  });
24345
24663
  }
24346
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Delete, null), "Delete")));
24664
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Delete, null), t('Delete'))));
24347
24665
  }
24348
24666
  /* harmony default export */ const components_StudyMeasurementsActions = (StudyMeasurementsActions);
24349
24667
  ;// ../../../extensions/cornerstone/src/components/StudySummaryWithActions.tsx
@@ -24549,7 +24867,7 @@ const getPanelModule = ({
24549
24867
  configuration: {
24550
24868
  ...props?.configuration
24551
24869
  },
24552
- segmentationRepresentationType: props?.segmentationRepresentationType
24870
+ segmentationRepresentationTypes: props?.segmentationRepresentationTypes
24553
24871
  });
24554
24872
  };
24555
24873
  const wrappedPanelSegmentationNoHeader = props => {
@@ -24560,17 +24878,17 @@ const getPanelModule = ({
24560
24878
  configuration: {
24561
24879
  ...props?.configuration
24562
24880
  },
24563
- segmentationRepresentationType: props?.segmentationRepresentationType
24881
+ segmentationRepresentationTypes: props?.segmentationRepresentationTypes
24564
24882
  });
24565
24883
  };
24566
24884
  const wrappedPanelSegmentationWithTools = props => {
24567
24885
  const {
24568
24886
  t
24569
- } = (0,es/* useTranslation */.Bd)('SegmentationTable');
24570
- const tKey = `${props.segmentationRepresentationType ?? 'Segmentation'} tools`;
24887
+ } = (0,es/* useTranslation */.Bd)('SegmentationPanel');
24888
+ const tKey = `${props.segmentationRepresentationTypes?.[0] ?? 'Segmentation'} tools`;
24571
24889
  const tValue = t(tKey);
24572
24890
  return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src.Toolbox, {
24573
- buttonSectionId: toolSectionMap[props.segmentationRepresentationType],
24891
+ buttonSectionId: toolSectionMap[props.segmentationRepresentationTypes?.[0]],
24574
24892
  title: tValue
24575
24893
  }), /*#__PURE__*/react.createElement(PanelSegmentation, {
24576
24894
  commandsManager: commandsManager,
@@ -24579,7 +24897,7 @@ const getPanelModule = ({
24579
24897
  configuration: {
24580
24898
  ...props?.configuration
24581
24899
  },
24582
- segmentationRepresentationType: props?.segmentationRepresentationType
24900
+ segmentationRepresentationTypes: props?.segmentationRepresentationTypes
24583
24901
  }));
24584
24902
  };
24585
24903
  return [{
@@ -24611,19 +24929,19 @@ const getPanelModule = ({
24611
24929
  name: 'panelSegmentationWithToolsLabelMap',
24612
24930
  iconName: 'tab-segmentation',
24613
24931
  iconLabel: 'Segmentation',
24614
- label: i18n_src/* default */.A.t('SegmentationTable:Labelmap'),
24932
+ label: i18n_src/* default */.A.t('SegmentationPanel:Labelmap'),
24615
24933
  component: props => wrappedPanelSegmentationWithTools({
24616
24934
  ...props,
24617
- segmentationRepresentationType: esm_enums.SegmentationRepresentations.Labelmap
24935
+ segmentationRepresentationTypes: [esm_enums.SegmentationRepresentations.Labelmap, esm_enums.SegmentationRepresentations.Surface]
24618
24936
  })
24619
24937
  }, {
24620
24938
  name: 'panelSegmentationWithToolsContour',
24621
24939
  iconName: 'tab-contours',
24622
24940
  iconLabel: 'Segmentation',
24623
- label: i18n_src/* default */.A.t('SegmentationTable:Contour'),
24941
+ label: i18n_src/* default */.A.t('SegmentationPanel:Contour'),
24624
24942
  component: props => wrappedPanelSegmentationWithTools({
24625
24943
  ...props,
24626
- segmentationRepresentationType: esm_enums.SegmentationRepresentations.Contour
24944
+ segmentationRepresentationTypes: [esm_enums.SegmentationRepresentations.Contour]
24627
24945
  })
24628
24946
  }];
24629
24947
  };
@@ -24663,7 +24981,7 @@ const handleSegmentChange = ({
24663
24981
  // Functions below use the segmentIndex object attribute so we have to do the conversion
24664
24982
  const segmentIndex = Object.values(segments)[newSelectedSegmentIndex]?.segmentIndex;
24665
24983
  segmentationService.setActiveSegment(segmentationId, segmentIndex);
24666
- segmentationService.jumpToSegmentCenter(segmentationId, segmentIndex, viewportId);
24984
+ segmentationService.jumpToSegmentNext(segmentationId, segmentIndex, undefined, direction);
24667
24985
  selectedSegmentObjectIndex = newSelectedSegmentIndex;
24668
24986
  };
24669
24987
  ;// ../../../extensions/cornerstone/src/utils/isReferenceViewable.ts
@@ -25124,11 +25442,15 @@ const setUpAnnotationEventHandlers = () => {
25124
25442
 
25125
25443
 
25126
25444
 
25445
+
25127
25446
  function MeasumentsMenu(props) {
25128
25447
  const {
25129
25448
  group,
25130
25449
  classNames
25131
25450
  } = props;
25451
+ const {
25452
+ t
25453
+ } = (0,es/* useTranslation */.Bd)('MeasurementTable');
25132
25454
  if (!group.items?.length) {
25133
25455
  console.log('No items to iterate', group.items);
25134
25456
  return null;
@@ -25160,7 +25482,7 @@ function MeasumentsMenu(props) {
25160
25482
  size: "icon",
25161
25483
  variant: "ghost",
25162
25484
  className: `h-6 w-6 transition-opacity ${isSelected || !isVisible ? 'opacity-100' : 'opacity-50 group-hover:opacity-100'}`,
25163
- "aria-label": isVisible ? 'Hide' : 'Show',
25485
+ "aria-label": isVisible ? t('Hide') : t('Show'),
25164
25486
  onClick: e => {
25165
25487
  e.stopPropagation();
25166
25488
  onAction(e, ['jumpToMeasurement', 'toggleVisibilityMeasurement']);
@@ -25189,7 +25511,7 @@ function MeasumentsMenu(props) {
25189
25511
  className: "text-foreground"
25190
25512
  }), /*#__PURE__*/react.createElement("span", {
25191
25513
  className: "pl-2"
25192
- }, "Delete")))));
25514
+ }, t('Delete'))))));
25193
25515
  }
25194
25516
  /* harmony default export */ const MeasurementsMenu = (MeasumentsMenu);
25195
25517
  ;// ../../../extensions/cornerstone/src/components/PanelAccordionTrigger.tsx