@ohif/app 3.12.0-beta.77 → 3.12.0-beta.78

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 (48) hide show
  1. package/dist/{147.bundle.23cc8fbbd94c0b65d337.js → 147.bundle.53fe889b205dd91c245b.js} +2 -2
  2. package/dist/{1604.bundle.5d95724cde8a8c23f7d7.js → 1604.bundle.0d3b54b754c97de7aa88.js} +5 -5
  3. package/dist/{1919.bundle.9abab6d9c380f9ef6f0b.js → 1919.bundle.099a3ad4025e527284b0.js} +6 -6
  4. package/dist/{2701.bundle.4c715c1d9bb7828886d8.js → 2701.bundle.6418ae6e9e372ccae322.js} +4 -4
  5. package/dist/{9856.bundle.31827ec7e09a8978744c.js → 306.bundle.a2380c4b23436c127faf.js} +110 -1
  6. package/dist/{9892.bundle.a09d4f672f8a784971a2.js → 3190.bundle.cd955568fe4d80ab2e4b.js} +114 -1
  7. package/dist/{3613.bundle.4a3b2f819e9698e9b7b3.js → 3613.bundle.f5fceb4697407a89921b.js} +60 -105
  8. package/dist/{4019.bundle.ddfa6fc4ccf74563cd40.js → 4019.bundle.6505ff57ca48af03da8a.js} +2 -2
  9. package/dist/{7197.bundle.f3676c560bf394aafd45.js → 4092.bundle.48390d480273857e794e.js} +338 -7
  10. package/dist/{7197.css → 4092.css} +1 -0
  11. package/dist/{4113.bundle.87c1437c5d1452a0c08b.js → 4113.bundle.8e8cca0c8fbf690e7b93.js} +2 -2
  12. package/dist/{414.bundle.2f752ae2409c02c49f10.js → 414.bundle.597500ee9c214b0a7212.js} +8 -8
  13. package/dist/{4202.bundle.1cef28d8aec1155d35d1.js → 4202.bundle.1c5271f1cacf5794aba7.js} +2 -2
  14. package/dist/{5349.bundle.14d76a9cb0f587c90614.js → 5349.bundle.6bf58c3e9e9571fa8a7d.js} +4 -4
  15. package/dist/{5457.bundle.635f651e4719be983799.js → 5457.bundle.9758280deb7db83edb99.js} +0 -8
  16. package/dist/{5485.bundle.919876def56a45d73ab2.js → 5485.bundle.aafe4c0e2e9e2afd878d.js} +0 -8
  17. package/dist/{5802.bundle.48e7f1324fc9e4486603.js → 5802.bundle.8922caf16c088b10cdb0.js} +2 -2
  18. package/dist/{6201.bundle.9f04a5cc79aec668f347.js → 6201.bundle.b0a52e8b23e83d7820d6.js} +2 -2
  19. package/dist/{8815.bundle.75f4d45eedb9c28c2181.js → 6725.bundle.75f59fc21a7fbecb9bce.js} +468 -37
  20. package/dist/{6991.bundle.594d1a749b0e67bbedf9.js → 6991.bundle.500dbaf5bec95a3d49d2.js} +2 -2
  21. package/dist/{3409.bundle.0e1e8c8a894cea8bc17b.js → 7948.bundle.8c0bd83ffaacabc3dcbd.js} +889 -238
  22. package/dist/{810.bundle.fd0a60e4edaeff3cc7ff.js → 810.bundle.d31e9fd894cac5ec768a.js} +6 -6
  23. package/dist/{8558.bundle.ad2f1dac0b4b583d75db.js → 8558.bundle.83d96d728f9f186ea5ad.js} +1 -1
  24. package/dist/{934.bundle.a3ba7abd77061cfa2d32.js → 934.bundle.a25daa6ed5038a83faf8.js} +2 -2
  25. package/dist/{1447.bundle.0e0f2e950690447bfda1.js → 9548.bundle.9e723f4ad09b9c1b431a.js} +69 -43
  26. package/dist/{8740.bundle.39b40ee21a873e824ce8.js → 9845.bundle.6ee5ca8fe9f68cefd56d.js} +5 -5
  27. package/dist/{9862.bundle.dc627e5f01fc4698a00f.js → 9862.bundle.e2c4c129f7907500b840.js} +2 -2
  28. package/dist/{app.bundle.c1735280b1ffec7296cf.js → app.bundle.0cf7e86910258d22401b.js} +483 -146
  29. package/dist/app.bundle.css +1 -1
  30. package/dist/{compute.bundle.08b8136bed028bf71f58.js → compute.bundle.f6f1236073e2a486ddfb.js} +3 -3
  31. package/dist/index.html +1 -1
  32. package/dist/{polySeg.bundle.a9790a5891bb286e7d4f.js → polySeg.bundle.d0ed88f3bfea700c211b.js} +3 -3
  33. package/dist/sw.js +1 -1
  34. package/package.json +20 -20
  35. package/dist/8740.css +0 -1
  36. /package/dist/{1459.bundle.84812caf93825d54325d.js → 1459.bundle.c878b794be71883de852.js} +0 -0
  37. /package/dist/{1807.bundle.48ef151b1f5c3a5e7e63.js → 1807.bundle.ade363b62ad3a0442a9c.js} +0 -0
  38. /package/dist/{213.bundle.9f5dbdcc51ecade9796c.js → 213.bundle.1cc1975ae90ca2eadfd5.js} +0 -0
  39. /package/dist/{2243.bundle.d485d2f4c40244af3599.js → 2243.bundle.a4c417be34f113e1fbc6.js} +0 -0
  40. /package/dist/{2424.bundle.dc021a7edf7f3a35176a.js → 2424.bundle.22082b8a1483bc47cbb1.js} +0 -0
  41. /package/dist/{2518.bundle.bdbd870da5355fdf502a.js → 2518.bundle.b21d8c66dc8deb8ba922.js} +0 -0
  42. /package/dist/{319.bundle.cd9383a345b9da2ba840.js → 319.bundle.f5adcbbef5767dedc45d.js} +0 -0
  43. /package/dist/{6027.bundle.5a2c33fa1eb3d810e7c1.js → 6027.bundle.5649e4e1fde732251102.js} +0 -0
  44. /package/dist/{7159.bundle.a472333e58e930b53e22.js → 7159.bundle.a5991a5d4f0dd8f1c95f.js} +0 -0
  45. /package/dist/{7412.bundle.0764ad3a00b3e9a044d9.js → 7412.bundle.94802a6a629f62daab88.js} +0 -0
  46. /package/dist/{7431.bundle.6dee1ec831da974a7433.js → 7431.bundle.ad1982d7c54a5931d409.js} +0 -0
  47. /package/dist/{7639.bundle.12fe44f68f57a135f9d8.js → 7639.bundle.c6ee8cf4672716943e89.js} +0 -0
  48. /package/dist/{85.bundle.38a0d049316b0e71f7d0.js → 85.bundle.b1586702f9300c017632.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
- (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[3409],{
2
+ (globalThis["webpackChunk"] = globalThis["webpackChunk"] || []).push([[7948],{
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 + 3072 modules
29
- var src = __webpack_require__(42606);
28
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3073 modules
29
+ var src = __webpack_require__(1246);
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__(42606);
120
+ /* harmony import */ var _ohif_ui_next__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1246);
121
121
  /* harmony import */ var _useViewportSegmentations__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(79063);
122
122
 
123
123
 
@@ -496,8 +496,8 @@ __webpack_require__.d(__webpack_exports__, {
496
496
  var react = __webpack_require__(86326);
497
497
  // EXTERNAL MODULE: ../../core/src/index.ts + 69 modules
498
498
  var src = __webpack_require__(42356);
499
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3072 modules
500
- var ui_next_src = __webpack_require__(42606);
499
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3073 modules
500
+ var ui_next_src = __webpack_require__(1246);
501
501
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/core/dist/esm/index.js + 1 modules
502
502
  var esm = __webpack_require__(15327);
503
503
  ;// ../../../extensions/cornerstone/src/components/ViewportDataOverlaySettingMenu/utils.ts
@@ -1657,7 +1657,7 @@ function useViewportSegmentations({
1657
1657
 
1658
1658
  /***/ }),
1659
1659
 
1660
- /***/ 23409:
1660
+ /***/ 37948:
1661
1661
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
1662
1662
 
1663
1663
  // ESM COMPAT FLAG
@@ -1718,6 +1718,7 @@ __webpack_require__.d(__webpack_exports__, {
1718
1718
  usePositionPresentationStore: () => (/* reexport */ usePositionPresentationStore/* usePositionPresentationStore */.q),
1719
1719
  useSegmentationPresentationStore: () => (/* reexport */ useSegmentationPresentationStore/* useSegmentationPresentationStore */.v),
1720
1720
  useSegmentations: () => (/* reexport */ useSegmentations/* useSegmentations */.j),
1721
+ useSelectedSegmentationsForViewportStore: () => (/* reexport */ useSelectedSegmentationsForViewportStore),
1721
1722
  useSynchronizersStore: () => (/* reexport */ useSynchronizersStore/* useSynchronizersStore */.U),
1722
1723
  utils: () => (/* reexport */ src_utils)
1723
1724
  });
@@ -1807,8 +1808,8 @@ function destroy() {
1807
1808
  var ai_dist_esm = __webpack_require__(75165);
1808
1809
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/polymorphic-segmentation/dist/esm/index.js + 14 modules
1809
1810
  var polymorphic_segmentation_dist_esm = __webpack_require__(56983);
1810
- // EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 139 modules
1811
- var default_src = __webpack_require__(11447);
1811
+ // EXTERNAL MODULE: ../../../extensions/default/src/index.ts + 141 modules
1812
+ var default_src = __webpack_require__(39548);
1812
1813
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/state.ts
1813
1814
  var state = __webpack_require__(71353);
1814
1815
  ;// ../../../extensions/cornerstone/src/utils/getViewportEnabledElement.ts
@@ -2246,6 +2247,10 @@ function initCornerstoneTools(configuration = {}) {
2246
2247
  (0,dist_esm.addTool)(ai_dist_esm/* LabelmapSlicePropagationTool */.Bj);
2247
2248
  (0,dist_esm.addTool)(ai_dist_esm/* MarkerLabelmapTool */.pY);
2248
2249
  (0,dist_esm.addTool)(dist_esm.RegionSegmentPlusTool);
2250
+ (0,dist_esm.addTool)(dist_esm.LivewireContourSegmentationTool);
2251
+ (0,dist_esm.addTool)(dist_esm.SculptorTool);
2252
+ (0,dist_esm.addTool)(dist_esm.SplineContourSegmentationTool);
2253
+ (0,dist_esm.addTool)(dist_esm.LabelMapEditWithContourTool);
2249
2254
  // Modify annotation tools to use dashed lines on SR
2250
2255
  const annotationStyle = {
2251
2256
  textBoxFontSize: '15px',
@@ -2302,7 +2307,11 @@ const toolNames = {
2302
2307
  SegmentLabel: dist_esm.SegmentLabelTool.toolName,
2303
2308
  LabelmapSlicePropagation: ai_dist_esm/* LabelmapSlicePropagationTool */.Bj.toolName,
2304
2309
  MarkerLabelmap: ai_dist_esm/* MarkerLabelmapTool */.pY.toolName,
2305
- RegionSegmentPlus: dist_esm.RegionSegmentPlusTool.toolName
2310
+ RegionSegmentPlus: dist_esm.RegionSegmentPlusTool.toolName,
2311
+ LivewireContourSegmentation: dist_esm.LivewireContourSegmentationTool.toolName,
2312
+ SculptorTool: dist_esm.SculptorTool.toolName,
2313
+ SplineContourSegmentation: dist_esm.SplineContourSegmentationTool.toolName,
2314
+ LabelMapEditWithContourTool: dist_esm.LabelMapEditWithContourTool.toolName
2306
2315
  };
2307
2316
 
2308
2317
  ;// ../../../extensions/cornerstone/src/utils/measurementServiceMappings/constants/supportedTools.js
@@ -7171,6 +7180,7 @@ async function init({
7171
7180
  toolbarService
7172
7181
  } = servicesManager.services;
7173
7182
  toolbarService.registerEventForToolbarUpdate(colorbarService, [colorbarService.EVENTS.STATE_CHANGED]);
7183
+ toolbarService.registerEventForToolbarUpdate(segmentationService, [segmentationService.EVENTS.SEGMENTATION_MODIFIED, segmentationService.EVENTS.SEGMENTATION_REPRESENTATION_MODIFIED, segmentationService.EVENTS.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED]);
7174
7184
  window.services = servicesManager.services;
7175
7185
  window.extensionManager = extensionManager;
7176
7186
  window.commandsManager = commandsManager;
@@ -7446,16 +7456,85 @@ function _showCPURenderingModal(uiModalService, hangingProtocolService) {
7446
7456
  inheritsFrom: 'ohif.overlayItem.instanceNumber'
7447
7457
  }]
7448
7458
  });
7449
- // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3072 modules
7450
- var ui_next_src = __webpack_require__(42606);
7459
+ // EXTERNAL MODULE: ../../ui-next/src/index.ts + 3073 modules
7460
+ var ui_next_src = __webpack_require__(1246);
7451
7461
  // EXTERNAL MODULE: ../../../node_modules/react-i18next/dist/es/index.js + 15 modules
7452
7462
  var es = __webpack_require__(99993);
7463
+ ;// ../../../extensions/cornerstone/src/components/ExportSegmentationSubMenuItem.tsx
7464
+
7465
+
7466
+
7467
+
7468
+ const ExportSegmentationSubMenuItem = ({
7469
+ segmentationId,
7470
+ segmentationRepresentationType,
7471
+ allowExport,
7472
+ actions
7473
+ }) => {
7474
+ const {
7475
+ t
7476
+ } = (0,es/* useTranslation */.Bd)('SegmentationTable');
7477
+ return /*#__PURE__*/react.createElement(react.Fragment, null, segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSub */.lvB, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubTrigger */.nVd, {
7478
+ className: "pl-1"
7479
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7480
+ className: "text-foreground"
7481
+ }), /*#__PURE__*/react.createElement("span", {
7482
+ className: "pl-2"
7483
+ }, 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, {
7484
+ className: "flex items-center pl-0"
7485
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Download, {
7486
+ className: "h-5 w-5"
7487
+ }), /*#__PURE__*/react.createElement("span", {
7488
+ className: "pl-1"
7489
+ }, t('Download'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7490
+ onClick: e => {
7491
+ e.preventDefault();
7492
+ actions.downloadCSVSegmentationReport(segmentationId);
7493
+ },
7494
+ disabled: !allowExport
7495
+ }, t('CSV Report')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7496
+ onClick: e => {
7497
+ e.preventDefault();
7498
+ actions.onSegmentationDownload(segmentationId);
7499
+ },
7500
+ disabled: !allowExport
7501
+ }, t('DICOM SEG')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7502
+ onClick: e => {
7503
+ e.preventDefault();
7504
+ actions.onSegmentationDownloadRTSS(segmentationId);
7505
+ },
7506
+ disabled: !allowExport
7507
+ }, t('DICOM RTSS')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
7508
+ className: "flex items-center pl-0"
7509
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7510
+ className: "h-5 w-5"
7511
+ }), /*#__PURE__*/react.createElement("span", {
7512
+ className: "pl-1 pt-1"
7513
+ }, t('Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7514
+ onClick: e => {
7515
+ e.preventDefault();
7516
+ actions.storeSegmentation(segmentationId);
7517
+ },
7518
+ disabled: !allowExport
7519
+ }, t('DICOM SEG'))))), segmentationRepresentationType === esm_enums.SegmentationRepresentations.Contour && /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7520
+ onClick: e => {
7521
+ e.preventDefault();
7522
+ actions.onSegmentationDownloadRTSS(segmentationId);
7523
+ },
7524
+ disabled: !allowExport
7525
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7526
+ className: "text-foreground"
7527
+ }), /*#__PURE__*/react.createElement("span", {
7528
+ className: "pl-2"
7529
+ }, t('Download DICOM RTSS')))));
7530
+ };
7453
7531
  ;// ../../../extensions/cornerstone/src/customizations/CustomDropdownMenuContent.tsx
7454
7532
 
7455
7533
 
7456
7534
 
7457
7535
 
7458
7536
 
7537
+
7459
7538
  /**
7460
7539
  * Custom dropdown menu component for segmentation panel that uses context for data
7461
7540
  */
@@ -7473,7 +7552,9 @@ const CustomDropdownMenuContent = () => {
7473
7552
  onSegmentationDelete,
7474
7553
  exportOptions,
7475
7554
  activeSegmentation,
7476
- activeSegmentationId
7555
+ activeSegmentationId,
7556
+ segmentationRepresentationType,
7557
+ disableEditing
7477
7558
  } = (0,ui_next_src/* useSegmentationTableContext */.dQ$)('CustomDropdownMenu');
7478
7559
 
7479
7560
  // Try to get segmentation data from expanded context first, fall back to table context
@@ -7527,8 +7608,11 @@ const CustomDropdownMenuContent = () => {
7527
7608
  };
7528
7609
  return /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuContent */.SQm, {
7529
7610
  align: "start"
7530
- }, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7531
- onClick: () => onSegmentationAdd(segmentationId)
7611
+ }, !disableEditing && /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7612
+ onClick: () => onSegmentationAdd({
7613
+ segmentationId,
7614
+ segmentationRepresentationType
7615
+ })
7532
7616
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Add, {
7533
7617
  className: "text-foreground"
7534
7618
  }), /*#__PURE__*/react.createElement("span", {
@@ -7545,49 +7629,12 @@ const CustomDropdownMenuContent = () => {
7545
7629
  className: "text-foreground"
7546
7630
  }), /*#__PURE__*/react.createElement("span", {
7547
7631
  className: "pl-2"
7548
- }, t('Rename'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSub */.lvB, null, /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSubTrigger */.nVd, {
7549
- className: "pl-1"
7550
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7551
- className: "text-foreground"
7552
- }), /*#__PURE__*/react.createElement("span", {
7553
- className: "pl-2"
7554
- }, 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, {
7555
- className: "flex items-center pl-0"
7556
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Download, {
7557
- className: "h-5 w-5"
7558
- }), /*#__PURE__*/react.createElement("span", {
7559
- className: "pl-1"
7560
- }, t('Download'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7561
- onClick: e => {
7562
- e.preventDefault();
7563
- actions.downloadCSVSegmentationReport(segmentationId);
7564
- },
7565
- disabled: !allowExport
7566
- }, t('CSV Report')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7567
- onClick: e => {
7568
- e.preventDefault();
7569
- actions.onSegmentationDownload(segmentationId);
7570
- },
7571
- disabled: !allowExport
7572
- }, t('DICOM SEG')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7573
- onClick: e => {
7574
- e.preventDefault();
7575
- actions.onSegmentationDownloadRTSS(segmentationId);
7576
- },
7577
- disabled: !allowExport
7578
- }, t('DICOM RTSS')), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuLabel */.lpj, {
7579
- className: "flex items-center pl-0"
7580
- }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Export, {
7581
- className: "h-5 w-5"
7582
- }), /*#__PURE__*/react.createElement("span", {
7583
- className: "pl-1 pt-1"
7584
- }, t('Export'))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7585
- onClick: e => {
7586
- e.preventDefault();
7587
- actions.storeSegmentation(segmentationId);
7588
- },
7589
- disabled: !allowExport
7590
- }, t('DICOM SEG'))))), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7632
+ }, t('Rename'))), /*#__PURE__*/react.createElement(ExportSegmentationSubMenuItem, {
7633
+ segmentationId: segmentationId,
7634
+ segmentationRepresentationType: segmentationRepresentationType,
7635
+ allowExport: allowExport,
7636
+ actions: actions
7637
+ }), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuSeparator */.mBJ, null), /*#__PURE__*/react.createElement(ui_next_src/* DropdownMenuItem */._26, {
7591
7638
  onClick: () => onSegmentationDelete(segmentationId)
7592
7639
  }, /*#__PURE__*/react.createElement(ui_next_src/* Icons */.FI1.Delete, {
7593
7640
  className: "text-red-600"
@@ -7707,11 +7754,83 @@ const CustomSegmentStatisticsHeader = ({
7707
7754
  className: "bg-input"
7708
7755
  }));
7709
7756
  };
7757
+ ;// ../../../extensions/cornerstone/src/components/SegmentationToolConfig.tsx
7758
+
7759
+
7760
+
7761
+ function SegmentationToolConfig() {
7762
+ const {
7763
+ commandsManager
7764
+ } = (0,src/* useSystem */.Jg)();
7765
+
7766
+ // Get initial states based on current configuration
7767
+ const [previewEdits, setPreviewEdits] = (0,react.useState)(false);
7768
+ const [segmentLabelEnabled, setSegmentLabelEnabled] = (0,react.useState)(false);
7769
+ const [toggleSegmentEnabled, setToggleSegmentEnabled] = (0,react.useState)(false);
7770
+ const [useCenterAsSegmentIndex, setUseCenterAsSegmentIndex] = (0,react.useState)(false);
7771
+ const handlePreviewEditsChange = checked => {
7772
+ setPreviewEdits(checked);
7773
+ commandsManager.run('toggleSegmentPreviewEdit', {
7774
+ toggle: checked
7775
+ });
7776
+ };
7777
+ const handleToggleSegmentEnabledChange = checked => {
7778
+ setToggleSegmentEnabled(checked);
7779
+ commandsManager.run('toggleSegmentSelect', {
7780
+ toggle: checked
7781
+ });
7782
+ };
7783
+ const handleUseCenterAsSegmentIndexChange = checked => {
7784
+ setUseCenterAsSegmentIndex(checked);
7785
+ commandsManager.run('toggleUseCenterSegmentIndex', {
7786
+ toggle: checked
7787
+ });
7788
+ };
7789
+ const handleSegmentLabelEnabledChange = checked => {
7790
+ setSegmentLabelEnabled(checked);
7791
+ commandsManager.run('toggleSegmentLabel', {
7792
+ enabled: checked
7793
+ });
7794
+ };
7795
+ return /*#__PURE__*/react.createElement("div", {
7796
+ className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-black px-2 py-3"
7797
+ }, /*#__PURE__*/react.createElement("div", {
7798
+ className: "flex items-center gap-2"
7799
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7800
+ checked: previewEdits,
7801
+ onCheckedChange: handlePreviewEditsChange
7802
+ }), /*#__PURE__*/react.createElement("span", {
7803
+ className: "text-foreground text-base"
7804
+ }, "Preview edits before creating")), /*#__PURE__*/react.createElement("div", {
7805
+ className: "flex items-center gap-2"
7806
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7807
+ checked: useCenterAsSegmentIndex,
7808
+ onCheckedChange: handleUseCenterAsSegmentIndexChange
7809
+ }), /*#__PURE__*/react.createElement("span", {
7810
+ className: "text-foreground text-base"
7811
+ }, "Use center as segment index")), /*#__PURE__*/react.createElement("div", {
7812
+ className: "flex items-center gap-2"
7813
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7814
+ checked: toggleSegmentEnabled,
7815
+ onCheckedChange: handleToggleSegmentEnabledChange
7816
+ }), /*#__PURE__*/react.createElement("span", {
7817
+ className: "text-foreground text-base"
7818
+ }, "Hover on segment border to activate")), /*#__PURE__*/react.createElement("div", {
7819
+ className: "flex items-center gap-2"
7820
+ }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7821
+ checked: segmentLabelEnabled,
7822
+ onCheckedChange: handleSegmentLabelEnabledChange
7823
+ }), /*#__PURE__*/react.createElement("span", {
7824
+ className: "text-foreground text-base"
7825
+ }, "Show segment name on hover")));
7826
+ }
7710
7827
  ;// ../../../extensions/cornerstone/src/customizations/segmentationPanelCustomization.tsx
7711
7828
 
7712
7829
 
7713
7830
 
7714
7831
 
7832
+
7833
+
7715
7834
  function getSegmentationPanelCustomization({
7716
7835
  commandsManager,
7717
7836
  servicesManager
@@ -7721,14 +7840,29 @@ function getSegmentationPanelCustomization({
7721
7840
  'panelSegmentation.customSegmentStatisticsHeader': CustomSegmentStatisticsHeader,
7722
7841
  'panelSegmentation.disableEditing': false,
7723
7842
  'panelSegmentation.showAddSegment': true,
7724
- 'panelSegmentation.onSegmentationAdd': () => {
7843
+ 'panelSegmentation.onSegmentationAdd': async ({
7844
+ segmentationRepresentationType = esm_enums.SegmentationRepresentations.Labelmap
7845
+ }) => {
7725
7846
  const {
7726
7847
  viewportGridService
7727
7848
  } = servicesManager.services;
7728
7849
  const viewportId = viewportGridService.getState().activeViewportId;
7729
- commandsManager.run('createLabelmapForViewport', {
7730
- viewportId
7731
- });
7850
+ if (segmentationRepresentationType === esm_enums.SegmentationRepresentations.Labelmap) {
7851
+ commandsManager.run('createLabelmapForViewport', {
7852
+ viewportId
7853
+ });
7854
+ } else if (segmentationRepresentationType === esm_enums.SegmentationRepresentations.Contour) {
7855
+ const segmentationId = await commandsManager.run('createContourForViewport', {
7856
+ viewportId
7857
+ });
7858
+ dist_esm.segmentation.config.style.setStyle({
7859
+ segmentationId,
7860
+ type: esm_enums.SegmentationRepresentations.Contour
7861
+ }, {
7862
+ fillAlpha: 0.5,
7863
+ renderFill: true
7864
+ });
7865
+ }
7732
7866
  },
7733
7867
  'panelSegmentation.tableMode': 'collapsed',
7734
7868
  'panelSegmentation.readableText': {
@@ -7749,67 +7883,11 @@ function getSegmentationPanelCustomization({
7749
7883
  lesionGlycolysis: 'Lesion Glycolysis',
7750
7884
  center: 'Center'
7751
7885
  },
7752
- 'segmentationToolbox.config': () => {
7753
- // Get initial states based on current configuration
7754
- const [previewEdits, setPreviewEdits] = (0,react.useState)(false);
7755
- const [segmentLabelEnabled, setSegmentLabelEnabled] = (0,react.useState)(false);
7756
- const [toggleSegmentEnabled, setToggleSegmentEnabled] = (0,react.useState)(false);
7757
- const [useCenterAsSegmentIndex, setUseCenterAsSegmentIndex] = (0,react.useState)(false);
7758
- const handlePreviewEditsChange = checked => {
7759
- setPreviewEdits(checked);
7760
- commandsManager.run('toggleSegmentPreviewEdit', {
7761
- toggle: checked
7762
- });
7763
- };
7764
- const handleToggleSegmentEnabledChange = checked => {
7765
- setToggleSegmentEnabled(checked);
7766
- commandsManager.run('toggleSegmentSelect', {
7767
- toggle: checked
7768
- });
7769
- };
7770
- const handleUseCenterAsSegmentIndexChange = checked => {
7771
- setUseCenterAsSegmentIndex(checked);
7772
- commandsManager.run('toggleUseCenterSegmentIndex', {
7773
- toggle: checked
7774
- });
7775
- };
7776
- const handleSegmentLabelEnabledChange = checked => {
7777
- setSegmentLabelEnabled(checked);
7778
- commandsManager.run('toggleSegmentLabel', {
7779
- enabled: checked
7780
- });
7781
- };
7782
- return /*#__PURE__*/react.createElement("div", {
7783
- className: "bg-muted flex flex-col gap-2 border-b border-b-[2px] border-black px-2 py-3"
7784
- }, /*#__PURE__*/react.createElement("div", {
7785
- className: "flex items-center gap-2"
7786
- }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7787
- checked: previewEdits,
7788
- onCheckedChange: handlePreviewEditsChange
7789
- }), /*#__PURE__*/react.createElement("span", {
7790
- className: "text-foreground text-base"
7791
- }, "Preview edits before creating")), /*#__PURE__*/react.createElement("div", {
7792
- className: "flex items-center gap-2"
7793
- }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7794
- checked: useCenterAsSegmentIndex,
7795
- onCheckedChange: handleUseCenterAsSegmentIndexChange
7796
- }), /*#__PURE__*/react.createElement("span", {
7797
- className: "text-foreground text-base"
7798
- }, "Use center as segment index")), /*#__PURE__*/react.createElement("div", {
7799
- className: "flex items-center gap-2"
7800
- }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7801
- checked: toggleSegmentEnabled,
7802
- onCheckedChange: handleToggleSegmentEnabledChange
7803
- }), /*#__PURE__*/react.createElement("span", {
7804
- className: "text-foreground text-base"
7805
- }, "Hover on segment border to activate")), /*#__PURE__*/react.createElement("div", {
7806
- className: "flex items-center gap-2"
7807
- }, /*#__PURE__*/react.createElement(ui_next_src/* Switch */.dOG, {
7808
- checked: segmentLabelEnabled,
7809
- onCheckedChange: handleSegmentLabelEnabledChange
7810
- }), /*#__PURE__*/react.createElement("span", {
7811
- className: "text-foreground text-base"
7812
- }, "Show segment name on hover")));
7886
+ 'labelMapSegmentationToolbox.config': () => {
7887
+ return /*#__PURE__*/react.createElement(SegmentationToolConfig, null);
7888
+ },
7889
+ 'contourSegmentationToolbox.config': () => {
7890
+ return /*#__PURE__*/react.createElement(SegmentationToolConfig, null);
7813
7891
  }
7814
7892
  };
7815
7893
  }
@@ -9031,10 +9109,10 @@ function getCustomizationModule({
9031
9109
  }];
9032
9110
  }
9033
9111
  /* harmony default export */ const src_getCustomizationModule = (getCustomizationModule);
9112
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/utilities/contourSegmentation/logicalOperators.js + 1 modules
9113
+ var logicalOperators = __webpack_require__(21536);
9034
9114
  // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/labelmap-interpolation/dist/esm/index.js + 2 modules
9035
9115
  var labelmap_interpolation_dist_esm = __webpack_require__(7927);
9036
- // EXTERNAL MODULE: ../../i18n/src/index.js + 210 modules
9037
- var i18n_src = __webpack_require__(68523);
9038
9116
  // EXTERNAL MODULE: ../../../node_modules/gl-matrix/esm/index.js + 1 modules
9039
9117
  var gl_matrix_esm = __webpack_require__(3823);
9040
9118
  ;// ../../../extensions/cornerstone/src/utils/imageSliceSync/toggleImageSliceSync.ts
@@ -9222,11 +9300,59 @@ function groupViewportsByModality(viewportGridService, displaySetService) {
9222
9300
  }
9223
9301
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/stores/useSynchronizersStore.ts
9224
9302
  var useSynchronizersStore = __webpack_require__(68578);
9303
+ // EXTERNAL MODULE: ../../../node_modules/zustand/esm/index.mjs + 1 modules
9304
+ var zustand_esm = __webpack_require__(78713);
9305
+ // EXTERNAL MODULE: ../../../node_modules/zustand/esm/middleware.mjs
9306
+ var middleware = __webpack_require__(21978);
9307
+ ;// ../../../extensions/cornerstone/src/stores/useSelectedSegmentationsForViewportStore.ts
9308
+
9309
+
9310
+ const PRESENTATION_TYPE_ID = 'selectedSegmentationsForViewportId';
9311
+ const DEBUG_STORE = false;
9312
+
9313
+ /**
9314
+ * Represents the state and actions for managing selected segmentations for a viewport by representation type.
9315
+ */
9316
+
9317
+ /**
9318
+ * Creates the Selected Segmentations For Viewport store.
9319
+ *
9320
+ * @param set - The zustand set function.
9321
+ * @returns The selected segmentations for viewport store state and actions.
9322
+ */
9323
+ const createSelectedSegmentationsForViewportStore = set => ({
9324
+ selectedSegmentationsForViewport: {},
9325
+ type: PRESENTATION_TYPE_ID,
9326
+ /**
9327
+ * Sets the selected segmentations for a given viewport id.
9328
+ */
9329
+ setSelectedSegmentationsForViewport: (key, value) => set(state => ({
9330
+ selectedSegmentationsForViewport: {
9331
+ ...state.selectedSegmentationsForViewport,
9332
+ [key]: value
9333
+ }
9334
+ }), false, 'setSelectedSegmentationsForViewport'),
9335
+ /**
9336
+ * Clears all selected segmentations for all viewports.
9337
+ */
9338
+ clearSelectedSegmentationsForViewportStore: () => set({
9339
+ selectedSegmentationsForViewport: {}
9340
+ }, false, 'clearSelectedSegmentationsForViewportStore')
9341
+ });
9342
+
9343
+ /**
9344
+ * Zustand store for managing selected segmentations for a viewport by representation type.
9345
+ * Applies devtools middleware when DEBUG_STORE is enabled.
9346
+ */
9347
+ const useSelectedSegmentationsForViewportStore = (0,zustand_esm/* create */.vt)()(DEBUG_STORE ? (0,middleware/* devtools */.lt)(createSelectedSegmentationsForViewportStore, {
9348
+ name: 'SelectedSegmentationsForViewportStore'
9349
+ }) : createSelectedSegmentationsForViewportStore);
9225
9350
  ;// ../../../extensions/cornerstone/src/stores/index.ts
9226
9351
 
9227
9352
 
9228
9353
 
9229
9354
 
9355
+
9230
9356
  // EXTERNAL MODULE: ../../../node_modules/html2canvas/dist/html2canvas.esm.js
9231
9357
  var html2canvas_esm = __webpack_require__(91037);
9232
9358
  ;// ../../../extensions/cornerstone/src/utils/CornerstoneViewportDownloadForm.tsx
@@ -10113,6 +10239,66 @@ let EasingFunctionEnum = /*#__PURE__*/function (EasingFunctionEnum) {
10113
10239
  return EasingFunctionEnum;
10114
10240
  }({});
10115
10241
  const EasingFunctionMap = new Map([[EasingFunctionEnum.EASE, ease], [EasingFunctionEnum.EASE_IN, easeIn], [EasingFunctionEnum.EASE_OUT, easeOut], [EasingFunctionEnum.EASE_IN_OUT, easeInOut], [EasingFunctionEnum.LINEAR, linear]]);
10242
+ // EXTERNAL MODULE: ../../i18n/src/index.js + 210 modules
10243
+ var i18n_src = __webpack_require__(68523);
10244
+ ;// ../../../extensions/cornerstone/src/utils/createSegmentationForViewport.ts
10245
+
10246
+
10247
+
10248
+ function _createDefaultSegments(createInitialSegment) {
10249
+ return createInitialSegment ? {
10250
+ 1: {
10251
+ label: `${i18n_src/* default */.A.t('Tools:Segment')} 1`,
10252
+ active: true
10253
+ }
10254
+ } : {};
10255
+ }
10256
+ /**
10257
+ * Creates a segmentation for the active viewport
10258
+ *
10259
+ * The created segmentation will be registered as a display set and also added
10260
+ * as a segmentation representation to the viewport.
10261
+ */
10262
+ async function createSegmentationForViewport(servicesManager, {
10263
+ viewportId,
10264
+ options = {},
10265
+ segmentationType
10266
+ }) {
10267
+ const {
10268
+ viewportGridService,
10269
+ displaySetService,
10270
+ segmentationService
10271
+ } = servicesManager.services;
10272
+ const {
10273
+ viewports
10274
+ } = viewportGridService.getState();
10275
+ const targetViewportId = viewportId;
10276
+ const viewport = viewports.get(targetViewportId);
10277
+
10278
+ // Todo: add support for multiple display sets
10279
+ const displaySetInstanceUID = options.displaySetInstanceUID || viewport.displaySetInstanceUIDs[0];
10280
+ const segs = segmentationService.getSegmentations();
10281
+ const label = options.label || `${i18n_src/* default */.A.t('Tools:Segmentation')} ${segs.length + 1}`;
10282
+ const segmentationId = options.segmentationId || `${esm.utilities.uuidv4()}`;
10283
+ const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
10284
+ const segmentationCreationOptions = {
10285
+ label,
10286
+ segmentationId,
10287
+ segments: _createDefaultSegments(options.createInitialSegment)
10288
+ };
10289
+
10290
+ // This will create the segmentation and register it as a display set
10291
+ const generatedSegmentationId = await (segmentationType === esm_enums.SegmentationRepresentations.Labelmap ? segmentationService.createLabelmapForDisplaySet(displaySet, segmentationCreationOptions) : segmentationService.createContourForDisplaySet(displaySet, segmentationCreationOptions));
10292
+
10293
+ // Also add the segmentation representation to the viewport
10294
+ await segmentationService.addSegmentationRepresentation(viewportId, {
10295
+ segmentationId,
10296
+ type: segmentationType
10297
+ });
10298
+ return generatedSegmentationId;
10299
+ }
10300
+ // EXTERNAL MODULE: ../../../node_modules/@cornerstonejs/tools/dist/esm/stateManagement/segmentation/index.js + 9 modules
10301
+ var segmentation = __webpack_require__(55126);
10116
10302
  ;// ../../../extensions/cornerstone/src/commandsModule.ts
10117
10303
 
10118
10304
 
@@ -10138,6 +10324,15 @@ const EasingFunctionMap = new Map([[EasingFunctionEnum.EASE, ease], [EasingFunct
10138
10324
 
10139
10325
 
10140
10326
 
10327
+
10328
+
10329
+
10330
+ const {
10331
+ add,
10332
+ intersect,
10333
+ subtract,
10334
+ copy
10335
+ } = dist_esm.utilities.contourSegmentation;
10141
10336
  const {
10142
10337
  DefaultHistoryMemo
10143
10338
  } = esm.utilities.HistoryMemo;
@@ -11048,7 +11243,8 @@ function commandsModule({
11048
11243
  value,
11049
11244
  itemId,
11050
11245
  toolName,
11051
- toolGroupIds = []
11246
+ toolGroupIds = [],
11247
+ bindings
11052
11248
  }) => {
11053
11249
  // Sometimes it is passed as value (tools with options), sometimes as itemId (toolbar buttons)
11054
11250
  toolName = toolName || itemId || value;
@@ -11056,13 +11252,17 @@ function commandsModule({
11056
11252
  toolGroupIds.forEach(toolGroupId => {
11057
11253
  actions.setToolActive({
11058
11254
  toolName,
11059
- toolGroupId
11255
+ toolGroupId,
11256
+ bindings
11060
11257
  });
11061
11258
  });
11062
11259
  },
11063
11260
  setToolActive: ({
11064
11261
  toolName,
11065
- toolGroupId = null
11262
+ toolGroupId = null,
11263
+ bindings = [{
11264
+ mouseButton: dist_esm.Enums.MouseBindings.Primary
11265
+ }]
11066
11266
  }) => {
11067
11267
  const {
11068
11268
  viewports
@@ -11085,9 +11285,7 @@ function commandsModule({
11085
11285
 
11086
11286
  // Set the new toolName to be active
11087
11287
  toolGroup.setToolActive(toolName, {
11088
- bindings: [{
11089
- mouseButton: dist_esm.Enums.MouseBindings.Primary
11090
- }]
11288
+ bindings
11091
11289
  });
11092
11290
  },
11093
11291
  // capture viewport
@@ -11601,42 +11799,27 @@ function commandsModule({
11601
11799
  viewportId,
11602
11800
  options = {}
11603
11801
  }) => {
11604
- const {
11605
- viewportGridService,
11606
- displaySetService,
11607
- segmentationService
11608
- } = servicesManager.services;
11609
- const {
11610
- viewports
11611
- } = viewportGridService.getState();
11612
- const targetViewportId = viewportId;
11613
- const viewport = viewports.get(targetViewportId);
11614
-
11615
- // Todo: add support for multiple display sets
11616
- const displaySetInstanceUID = options.displaySetInstanceUID || viewport.displaySetInstanceUIDs[0];
11617
- const segs = segmentationService.getSegmentations();
11618
- const label = options.label || `${i18n_src/* default */.A.t('Tools:Segmentation')} ${segs.length + 1}`;
11619
- const segmentationId = options.segmentationId || `${esm.utilities.uuidv4()}`;
11620
- const displaySet = displaySetService.getDisplaySetByUID(displaySetInstanceUID);
11621
-
11622
- // This will create the segmentation and register it as a display set
11623
- const generatedSegmentationId = await segmentationService.createLabelmapForDisplaySet(displaySet, {
11624
- label,
11625
- segmentationId,
11626
- segments: options.createInitialSegment ? {
11627
- 1: {
11628
- label: `${i18n_src/* default */.A.t('Tools:Segment')} 1`,
11629
- active: true
11630
- }
11631
- } : {}
11802
+ return createSegmentationForViewport(servicesManager, {
11803
+ viewportId,
11804
+ options,
11805
+ segmentationType: esm_enums.SegmentationRepresentations.Labelmap
11632
11806
  });
11633
-
11634
- // Also add the segmentation representation to the viewport
11635
- await segmentationService.addSegmentationRepresentation(viewportId, {
11636
- segmentationId,
11637
- type: dist_esm.Enums.SegmentationRepresentations.Labelmap
11807
+ },
11808
+ /**
11809
+ * Creates a contour for the active viewport
11810
+ *
11811
+ * The created contour will be registered as a display set and also added
11812
+ * as a segmentation representation to the viewport.
11813
+ */
11814
+ createContourForViewport: async ({
11815
+ viewportId,
11816
+ options = {}
11817
+ }) => {
11818
+ return createSegmentationForViewport(servicesManager, {
11819
+ viewportId,
11820
+ options,
11821
+ segmentationType: esm_enums.SegmentationRepresentations.Contour
11638
11822
  });
11639
- return generatedSegmentationId;
11640
11823
  },
11641
11824
  /**
11642
11825
  * Sets the active segmentation for a viewport
@@ -11656,12 +11839,13 @@ function commandsModule({
11656
11839
  * @param props.segmentationId - The ID of the segmentation to add the segment to
11657
11840
  */
11658
11841
  addSegmentCommand: ({
11659
- segmentationId
11842
+ segmentationId,
11843
+ config
11660
11844
  }) => {
11661
11845
  const {
11662
11846
  segmentationService
11663
11847
  } = servicesManager.services;
11664
- segmentationService.addSegment(segmentationId);
11848
+ segmentationService.addSegment(segmentationId, config);
11665
11849
  },
11666
11850
  /**
11667
11851
  * Sets the active segment and jumps to its center
@@ -12471,6 +12655,193 @@ function commandsModule({
12471
12655
  newAnnotation,
12472
12656
  deleting
12473
12657
  });
12658
+ },
12659
+ activateSelectedSegmentationOfType: ({
12660
+ segmentationRepresentationType
12661
+ }) => {
12662
+ const {
12663
+ segmentationService,
12664
+ viewportGridService
12665
+ } = servicesManager.services;
12666
+ const activeViewportId = viewportGridService.getActiveViewportId();
12667
+ const {
12668
+ selectedSegmentationsForViewport
12669
+ } = useSelectedSegmentationsForViewportStore.getState();
12670
+ const segmentationId = selectedSegmentationsForViewport[activeViewportId]?.get(segmentationRepresentationType);
12671
+ if (!segmentationId) {
12672
+ return;
12673
+ }
12674
+ segmentationService.setActiveSegmentation(activeViewportId, segmentationId);
12675
+ },
12676
+ setDynamicCursorSizeForSculptorTool: ({
12677
+ value: isDynamicCursorSize
12678
+ }) => {
12679
+ const viewportId = viewportGridService.getActiveViewportId();
12680
+ const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
12681
+ const sculptorToolInstance = toolGroup.getToolInstance(toolNames.SculptorTool);
12682
+ const oldConfiguration = sculptorToolInstance.configuration;
12683
+ sculptorToolInstance.configuration = {
12684
+ ...oldConfiguration,
12685
+ updateCursorSize: isDynamicCursorSize ? 'dynamic' : ''
12686
+ };
12687
+ },
12688
+ setInterpolationToolConfiguration: ({
12689
+ value: interpolateContours,
12690
+ toolNames
12691
+ }) => {
12692
+ const viewportId = viewportGridService.getActiveViewportId();
12693
+ const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
12694
+
12695
+ // Set the interpolation configuration for the active tool.
12696
+ const activeTool = toolGroupService.getActiveToolForViewport(viewportId);
12697
+ const interpolationConfig = {
12698
+ interpolation: {
12699
+ enabled: interpolateContours,
12700
+ showInterpolationPolyline: true
12701
+ }
12702
+ };
12703
+ toolGroup.setToolConfiguration(activeTool, interpolationConfig);
12704
+
12705
+ // Now set the interpolation configuration for the other tools specified.
12706
+ if (toolNames) {
12707
+ Object.values(toolGroup.getToolInstances()).forEach(toolInstance => {
12708
+ if (toolNames?.includes(toolInstance.toolName)) {
12709
+ toolGroup.setToolConfiguration(toolInstance.toolName, interpolationConfig);
12710
+ }
12711
+ });
12712
+ }
12713
+ },
12714
+ setSimplifiedSplineForSplineContourSegmentationTool: ({
12715
+ value: simplifiedSpline
12716
+ }) => {
12717
+ const viewportId = viewportGridService.getActiveViewportId();
12718
+ const toolGroup = toolGroupService.getToolGroupForViewport(viewportId);
12719
+ Object.values(toolGroup.getToolInstances()).forEach(toolInstance => {
12720
+ if (toolInstance instanceof dist_esm.SplineContourSegmentationTool) {
12721
+ const oldConfiguration = toolInstance.configuration;
12722
+ toolInstance.configuration = {
12723
+ ...oldConfiguration,
12724
+ simplifiedSpline
12725
+ };
12726
+ }
12727
+ });
12728
+ },
12729
+ removeSmallContours: ({
12730
+ areaThreshold: threshold
12731
+ }) => {
12732
+ const viewportId = viewportGridService.getActiveViewportId();
12733
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12734
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12735
+ if (!activeSegmentation || !activeSegment) {
12736
+ return;
12737
+ }
12738
+ const {
12739
+ removeContourIslands
12740
+ } = segmentation.utilities;
12741
+ removeContourIslands(activeSegmentation.segmentationId, activeSegment.segmentIndex, {
12742
+ threshold
12743
+ });
12744
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12745
+ renderingEngine.render();
12746
+ },
12747
+ applyLogicalContourOperation: ({
12748
+ segmentAInfo,
12749
+ segmentBInfo,
12750
+ resultSegmentInfo,
12751
+ logicalOperation
12752
+ }) => {
12753
+ switch (logicalOperation) {
12754
+ case logicalOperators/* LogicalOperation */.Dp.Union:
12755
+ add(segmentAInfo, segmentBInfo, resultSegmentInfo);
12756
+ break;
12757
+ case logicalOperators/* LogicalOperation */.Dp.Intersect:
12758
+ intersect(segmentAInfo, segmentBInfo, resultSegmentInfo);
12759
+ break;
12760
+ case logicalOperators/* LogicalOperation */.Dp.Subtract:
12761
+ subtract(segmentAInfo, segmentBInfo, resultSegmentInfo);
12762
+ break;
12763
+ default:
12764
+ throw new Error('Unsupported logical operation');
12765
+ break;
12766
+ }
12767
+ },
12768
+ copyContourSegment: ({
12769
+ sourceSegmentInfo,
12770
+ targetSegmentInfo
12771
+ }) => {
12772
+ if (!targetSegmentInfo) {
12773
+ targetSegmentInfo = {
12774
+ segmentationId: sourceSegmentInfo.segmentationId,
12775
+ segmentIndex: segmentationService.getNextAvailableSegmentIndex(sourceSegmentInfo.segmentationId)
12776
+ };
12777
+ segmentationService.addSegment(targetSegmentInfo.segmentationId, {
12778
+ segmentIndex: targetSegmentInfo.segmentIndex
12779
+ });
12780
+ }
12781
+ copy(sourceSegmentInfo, targetSegmentInfo);
12782
+ },
12783
+ smoothContours: () => {
12784
+ const viewportId = viewportGridService.getActiveViewportId();
12785
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12786
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12787
+ if (!activeSegmentation || !activeSegment) {
12788
+ return;
12789
+ }
12790
+ const {
12791
+ smoothContours
12792
+ } = segmentation.utilities;
12793
+ smoothContours(activeSegmentation.segmentationId, activeSegment.segmentIndex);
12794
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12795
+ renderingEngine.render();
12796
+ },
12797
+ removeContourHoles: () => {
12798
+ const viewportId = viewportGridService.getActiveViewportId();
12799
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12800
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12801
+ if (!activeSegmentation || !activeSegment) {
12802
+ return;
12803
+ }
12804
+ const {
12805
+ removeContourHoles
12806
+ } = segmentation.utilities;
12807
+ removeContourHoles(activeSegmentation.segmentationId, activeSegment.segmentIndex);
12808
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12809
+ renderingEngine.render();
12810
+ },
12811
+ decimateContours: () => {
12812
+ const viewportId = viewportGridService.getActiveViewportId();
12813
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12814
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12815
+ if (!activeSegmentation || !activeSegment) {
12816
+ return;
12817
+ }
12818
+ const {
12819
+ decimateContours
12820
+ } = segmentation.utilities;
12821
+ decimateContours(activeSegmentation.segmentationId, activeSegment.segmentIndex);
12822
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12823
+ renderingEngine.render();
12824
+ },
12825
+ convertContourHoles: () => {
12826
+ const viewportId = viewportGridService.getActiveViewportId();
12827
+ const activeSegmentation = segmentationService.getActiveSegmentation(viewportId);
12828
+ const activeSegment = segmentationService.getActiveSegment(viewportId);
12829
+ if (!activeSegmentation || !activeSegment) {
12830
+ return;
12831
+ }
12832
+ const targetSegmentInfo = {
12833
+ segmentationId: activeSegmentation.segmentationId,
12834
+ segmentIndex: segmentationService.getNextAvailableSegmentIndex(activeSegmentation.segmentationId)
12835
+ };
12836
+ segmentationService.addSegment(targetSegmentInfo.segmentationId, {
12837
+ segmentIndex: targetSegmentInfo.segmentIndex
12838
+ });
12839
+ const {
12840
+ convertContourHoles
12841
+ } = segmentation.utilities;
12842
+ convertContourHoles(activeSegmentation.segmentationId, activeSegment.segmentIndex, targetSegmentInfo.segmentationId, targetSegmentInfo.segmentIndex);
12843
+ const renderingEngine = cornerstoneViewportService.getRenderingEngine();
12844
+ renderingEngine.render();
12474
12845
  }
12475
12846
  };
12476
12847
  const definitions = {
@@ -12692,6 +13063,9 @@ function commandsModule({
12692
13063
  createLabelmapForViewport: {
12693
13064
  commandFn: actions.createLabelmapForViewport
12694
13065
  },
13066
+ createContourForViewport: {
13067
+ commandFn: actions.createContourForViewport
13068
+ },
12695
13069
  setActiveSegmentation: {
12696
13070
  commandFn: actions.setActiveSegmentation
12697
13071
  },
@@ -12792,7 +13166,18 @@ function commandsModule({
12792
13166
  endRecordingForAnnotationGroup: actions.endRecordingForAnnotationGroup,
12793
13167
  toggleSegmentLabel: actions.toggleSegmentLabel,
12794
13168
  jumpToMeasurementViewport: actions.jumpToMeasurementViewport,
12795
- initializeSegmentLabelTool: actions.initializeSegmentLabelTool
13169
+ initializeSegmentLabelTool: actions.initializeSegmentLabelTool,
13170
+ activateSelectedSegmentationOfType: actions.activateSelectedSegmentationOfType,
13171
+ setDynamicCursorSizeForSculptorTool: actions.setDynamicCursorSizeForSculptorTool,
13172
+ setSimplifiedSplineForSplineContourSegmentationTool: actions.setSimplifiedSplineForSplineContourSegmentationTool,
13173
+ removeSmallContours: actions.removeSmallContours,
13174
+ applyLogicalContourOperation: actions.applyLogicalContourOperation,
13175
+ copyContourSegment: actions.copyContourSegment,
13176
+ smoothContours: actions.smoothContours,
13177
+ removeContourHoles: actions.removeContourHoles,
13178
+ decimateContours: actions.decimateContours,
13179
+ convertContourHoles: actions.convertContourHoles,
13180
+ setInterpolationToolConfiguration: actions.setInterpolationToolConfiguration
12796
13181
  };
12797
13182
  return {
12798
13183
  actions,
@@ -17343,8 +17728,8 @@ const ViewportColorbarsContainer = /*#__PURE__*/(0,react.memo)(function Viewport
17343
17728
 
17344
17729
 
17345
17730
  /* harmony default export */ const components_ViewportColorbar = (ViewportColorbar_ViewportColorbarsContainer);
17346
- // EXTERNAL MODULE: ../../core/src/hooks/index.ts + 3 modules
17347
- var src_hooks = __webpack_require__(69419);
17731
+ // EXTERNAL MODULE: ../../core/src/hooks/index.ts + 5 modules
17732
+ var src_hooks = __webpack_require__(85490);
17348
17733
  // EXTERNAL MODULE: ../../core/src/services/ToolBarService/ToolbarService.ts
17349
17734
  var ToolbarService = __webpack_require__(93813);
17350
17735
  ;// ../../../extensions/cornerstone/src/components/AdvancedRenderingControls/AdvancedRenderingControls.tsx
@@ -18661,7 +19046,9 @@ const SegmentationService_EVENTS = {
18661
19046
  // fired when the active segment is loaded in SEG or RTSTRUCT
18662
19047
  SEGMENT_LOADING_COMPLETE: 'event::segment_loading_complete',
18663
19048
  // loading completed for all segments
18664
- SEGMENTATION_LOADING_COMPLETE: 'event::segmentation_loading_complete'
19049
+ SEGMENTATION_LOADING_COMPLETE: 'event::segmentation_loading_complete',
19050
+ // fired when a contour annotation cut merge process is completed
19051
+ ANNOTATION_CUT_MERGE_PROCESS_COMPLETED: 'event::annotation_cut_merge_process_completed'
18665
19052
  };
18666
19053
  const VALUE_TYPES = {};
18667
19054
  class SegmentationService extends src/* PubSubService */.Rc {
@@ -18752,6 +19139,14 @@ class SegmentationService extends src/* PubSubService */.Rc {
18752
19139
  segmentationId
18753
19140
  });
18754
19141
  };
19142
+ this._onAnnotationCutMergeProcessCompletedFromSource = evt => {
19143
+ const {
19144
+ segmentationId
19145
+ } = evt.detail;
19146
+ this._broadcastEvent(this.EVENTS.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, {
19147
+ segmentationId
19148
+ });
19149
+ };
18755
19150
  this._segmentationIdToColorLUTIndexMap = new Map();
18756
19151
  this.servicesManager = servicesManager;
18757
19152
  this._segmentationGroupStatsMap = new Map();
@@ -18903,6 +19298,21 @@ class SegmentationService extends src/* PubSubService */.Rc {
18903
19298
  * @returns A promise that resolves to the created segmentation ID.
18904
19299
  */
18905
19300
  async createLabelmapForDisplaySet(displaySet, options) {
19301
+ return this._createSegmentationForDisplaySet(displaySet, LABELMAP, options);
19302
+ }
19303
+ async createContourForDisplaySet(displaySet, options) {
19304
+ return this._createSegmentationForDisplaySet(displaySet, CONTOUR, options);
19305
+ }
19306
+
19307
+ /**
19308
+ * Private method to create segmentation for a display set with the specified type
19309
+ *
19310
+ * @param displaySet - The display set to create the segmentation for
19311
+ * @param segmentationType - The type of segmentation (SegmentationRepresentations enum)
19312
+ * @param options - Optional parameters for creating the segmentation
19313
+ * @returns A promise that resolves to the created segmentation ID
19314
+ */
19315
+ async _createSegmentationForDisplaySet(displaySet, segmentationType, options) {
18906
19316
  // Todo: random does not makes sense, make this better, like
18907
19317
  // labelmap 1, 2, 3 etc
18908
19318
  const segmentationId = options?.segmentationId ?? `${esm.utilities.uuidv4()}`;
@@ -18921,7 +19331,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
18921
19331
  const segmentationPublicInput = {
18922
19332
  segmentationId,
18923
19333
  representation: {
18924
- type: LABELMAP,
19334
+ type: segmentationType,
18925
19335
  data: {
18926
19336
  imageIds: segImageIds,
18927
19337
  // referencedVolumeId: this._getVolumeIdForDisplaySet(displaySet),
@@ -19275,6 +19685,15 @@ class SegmentationService extends src/* PubSubService */.Rc {
19275
19685
  hasCustomStyles(specifier) {
19276
19686
  return dist_esm.segmentation.config.style.hasCustomStyle(specifier);
19277
19687
  }
19688
+ getNextAvailableSegmentIndex(segmentationId) {
19689
+ const csSegmentation = this.getCornerstoneSegmentation(segmentationId);
19690
+ // grab the next available segment index based on the object keys,
19691
+ // so basically get the highest segment index value + 1
19692
+
19693
+ const segmentKeys = Object.keys(csSegmentation.segments);
19694
+ return segmentKeys.length === 0 ? 1 : Math.max(...segmentKeys.map(Number)) + 1;
19695
+ }
19696
+
19278
19697
  /**
19279
19698
  * Adds a new segment to the specified segmentation.
19280
19699
  * @param segmentationId - The ID of the segmentation to add the segment to.
@@ -19296,10 +19715,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19296
19715
  const csSegmentation = this.getCornerstoneSegmentation(segmentationId);
19297
19716
  let segmentIndex = config.segmentIndex;
19298
19717
  if (!segmentIndex) {
19299
- // grab the next available segment index based on the object keys,
19300
- // so basically get the highest segment index value + 1
19301
- const segmentKeys = Object.keys(csSegmentation.segments);
19302
- segmentIndex = segmentKeys.length === 0 ? 1 : Math.max(...segmentKeys.map(Number)) + 1;
19718
+ segmentIndex = this.getNextAvailableSegmentIndex(segmentationId);
19303
19719
  }
19304
19720
 
19305
19721
  // update the segmentation
@@ -19846,6 +20262,7 @@ class SegmentationService extends src/* PubSubService */.Rc {
19846
20262
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_ADDED, this._onSegmentationRepresentationModifiedFromSource);
19847
20263
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_REPRESENTATION_REMOVED, this._onSegmentationRepresentationModifiedFromSource);
19848
20264
  esm.eventTarget.addEventListener(dist_esm.Enums.Events.SEGMENTATION_ADDED, this._onSegmentationAddedFromSource);
20265
+ esm.eventTarget.addEventListener(dist_esm.Enums.Events.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED, this._onAnnotationCutMergeProcessCompletedFromSource);
19849
20266
  }
19850
20267
  getCornerstoneSegmentation(segmentationId) {
19851
20268
  return dist_esm.segmentation.state.getSegmentation(segmentationId);
@@ -22540,14 +22957,130 @@ function getSopClassHandlerModule(params) {
22540
22957
  var useActiveViewportSegmentationRepresentations = __webpack_require__(9234);
22541
22958
  // EXTERNAL MODULE: ../../../extensions/cornerstone/src/hooks/useMeasurements.ts
22542
22959
  var useMeasurements = __webpack_require__(19214);
22960
+ ;// ../../../extensions/cornerstone/src/components/SegmentationUtilityButton.tsx
22961
+ function SegmentationUtilityButton_extends() { return SegmentationUtilityButton_extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, SegmentationUtilityButton_extends.apply(null, arguments); }
22962
+
22963
+
22964
+
22965
+ /**
22966
+ * A button that represents a segmentation utility.
22967
+ * It is implicitly the PopoverTrigger for the options Popover panel that is
22968
+ * opened in the PanelSegmentation component. It in essence is the PopoverTrigger
22969
+ * because typically this button has the associated options to display in the Popover.
22970
+ * Furthermore it also typically has a command for toggling the activeSegmentationUtility
22971
+ * value in the UIStateStore that triggers the fetching of its options.
22972
+
22973
+ * @param props - The props for the button.
22974
+ * @param props.className - The class name for the button.
22975
+ * @param props.isActive - Whether the button is active
22976
+ * @param props.id - The id of the button.
22977
+ */
22978
+ function SegmentationUtilityButton(props) {
22979
+ const {
22980
+ className,
22981
+ isActive,
22982
+ id
22983
+ } = props;
22984
+ const activeSegmentationUtility = (0,default_src.useUIStateStore)(store => store.uiState.activeSegmentationUtility);
22985
+ 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');
22986
+ const handleMouseDownCapture = (0,react.useCallback)(event => {
22987
+ if (activeSegmentationUtility === id) {
22988
+ // If this active button is clicked, prevent the default Popover
22989
+ // behaviour of closing the Popover on a pointer/mouse down.
22990
+ // Not doing this will cause the Popover to close and then reopen again.
22991
+ // Why? Because propagating this event will cause PanelSegmentation to
22992
+ // close the Popover by clearing the activeSegmentationUtility. Then
22993
+ // this button will set the activeSegmentationUtility again and the
22994
+ // Popover will reopen.
22995
+ event.preventDefault();
22996
+ event.stopPropagation();
22997
+ }
22998
+ }, [activeSegmentationUtility, id]);
22999
+ return /*#__PURE__*/react.createElement("div", {
23000
+ onPointerDownCapture: handleMouseDownCapture
23001
+ }, /*#__PURE__*/react.createElement(ui_next_src/* ToolButton */.T0e, SegmentationUtilityButton_extends({}, props, {
23002
+ className: toolButtonClassName
23003
+ })));
23004
+ }
23005
+ /* harmony default export */ const components_SegmentationUtilityButton = (SegmentationUtilityButton);
23006
+ ;// ../../../extensions/cornerstone/src/utils/segmentationExportUtils.ts
23007
+
23008
+ /**
23009
+ * Checks if a labelmap segmentation has exportable data
23010
+ * A label map is exportable if it has any pixel data and
23011
+ * it is referenced by a display set that is reconstructable.
23012
+ *
23013
+ * @param labelmap - The labelmap representation data
23014
+ * @param displaySetService - The display set service instance
23015
+ * @returns boolean - Whether the labelmap has exportable data
23016
+ */
23017
+ const hasExportableLabelMapData = (labelmap, displaySetService) => {
23018
+ if (!labelmap) {
23019
+ return false;
23020
+ }
23021
+ const imageIds = labelmap?.imageIds;
23022
+ if (!imageIds?.length) {
23023
+ return false;
23024
+ }
23025
+ const hasPixelData = imageIds.some(imageId => {
23026
+ const pixelData = esm.cache.getImage(imageId)?.getPixelData();
23027
+ if (!pixelData) {
23028
+ return false;
23029
+ }
23030
+ for (let i = 0; i < pixelData.length; i++) {
23031
+ if (pixelData[i] !== 0) {
23032
+ return true;
23033
+ }
23034
+ }
23035
+ });
23036
+ if (!hasPixelData) {
23037
+ return false;
23038
+ }
23039
+ const referencedImageIds = labelmap?.referencedImageIds;
23040
+ if (!referencedImageIds) {
23041
+ return false;
23042
+ }
23043
+ const firstImageId = referencedImageIds[0];
23044
+ const instance = esm.metaData.get('instance', firstImageId);
23045
+ if (!instance) {
23046
+ return false;
23047
+ }
23048
+ const SOPInstanceUID = instance.SOPInstanceUID || instance.SopInstanceUID;
23049
+ const SeriesInstanceUID = instance.SeriesInstanceUID;
23050
+ const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(SOPInstanceUID, SeriesInstanceUID);
23051
+ return displaySet?.isReconstructable;
23052
+ };
23053
+
23054
+ /**
23055
+ * Checks if a contour segmentation has exportable data
23056
+ * A contour is exportable if it has any contour annotation/geometry data.
23057
+ *
23058
+ * @param contour - The contour representation data
23059
+ * @returns boolean - Whether the contour has exportable data
23060
+ */
23061
+ const hasExportableContourData = contour => {
23062
+ if (!contour) {
23063
+ return false;
23064
+ }
23065
+ const contourAnnotationUIDsMap = contour?.annotationUIDsMap;
23066
+ if (!contourAnnotationUIDsMap) {
23067
+ return false;
23068
+ }
23069
+ return contourAnnotationUIDsMap.size > 0;
23070
+ };
22543
23071
  ;// ../../../extensions/cornerstone/src/panels/PanelSegmentation.tsx
22544
23072
 
22545
23073
 
22546
23074
 
22547
23075
 
22548
23076
 
23077
+
23078
+
23079
+
23080
+
22549
23081
  function PanelSegmentation({
22550
- children
23082
+ children,
23083
+ segmentationRepresentationType
22551
23084
  }) {
22552
23085
  const {
22553
23086
  commandsManager,
@@ -22555,12 +23088,56 @@ function PanelSegmentation({
22555
23088
  } = (0,src/* useSystem */.Jg)();
22556
23089
  const {
22557
23090
  customizationService,
22558
- displaySetService
23091
+ displaySetService,
23092
+ viewportGridService,
23093
+ toolbarService,
23094
+ segmentationService
22559
23095
  } = servicesManager.services;
23096
+ const {
23097
+ activeViewportId
23098
+ } = viewportGridService.getState();
23099
+ const utilitiesSectionMap = {
23100
+ [esm_enums.SegmentationRepresentations.Labelmap]: toolbarService.sections.labelMapSegmentationUtilities,
23101
+ [esm_enums.SegmentationRepresentations.Contour]: toolbarService.sections.contourSegmentationUtilities
23102
+ };
23103
+ const selectedSegmentationsForViewportMap = useSelectedSegmentationsForViewportStore(store => store.selectedSegmentationsForViewport[activeViewportId]);
23104
+ const selectedSegmentationIdForType = segmentationRepresentationType ? selectedSegmentationsForViewportMap?.get(segmentationRepresentationType) : segmentationService?.getActiveSegmentation(activeViewportId)?.segmentationId;
23105
+ const buttonSection = utilitiesSectionMap[segmentationRepresentationType];
23106
+ const {
23107
+ activeToolOptions: activeUtilityOptions
23108
+ } = (0,src/* useActiveToolOptions */.KP)({
23109
+ buttonSectionId: buttonSection
23110
+ });
22560
23111
  const {
22561
23112
  segmentationsWithRepresentations,
22562
23113
  disabled
22563
23114
  } = (0,useActiveViewportSegmentationRepresentations/* useActiveViewportSegmentationRepresentations */.c)();
23115
+ const setUIState = (0,default_src.useUIStateStore)(store => store.setUIState);
23116
+
23117
+ // useEffect for handling clicks on any of the non-active viewports.
23118
+ // The ViewportGrid stops the propagation of pointer/mouse events
23119
+ // for non-active viewports so the Popover below
23120
+ // is not closed when clicking on any of the non-active viewports.
23121
+ (0,react.useEffect)(() => {
23122
+ setUIState('activeSegmentationUtility', null);
23123
+ toolbarService.refreshToolbarState({
23124
+ viewportId: activeViewportId
23125
+ });
23126
+ }, [activeViewportId, setUIState, toolbarService]);
23127
+
23128
+ // The callback for handling clicks outside of the Popover and, the SegmentationUtilityButton
23129
+ // that triggered it to open. Clicks outside those components must close the Popover.
23130
+ // The Popover is made visible whenever the options associated with the
23131
+ // activeSegmentationUtility exist. Thus clearing the activeSegmentationUtility
23132
+ // clears the associated options and will keep the Popover closed.
23133
+ const handlePopoverOpenChange = (0,react.useCallback)(open => {
23134
+ if (!open) {
23135
+ setUIState('activeSegmentationUtility', null);
23136
+ toolbarService.refreshToolbarState({
23137
+ viewportId: activeViewportId
23138
+ });
23139
+ }
23140
+ }, [activeViewportId, setUIState, toolbarService]);
22564
23141
 
22565
23142
  // Extract customization options
22566
23143
  const segmentationTableMode = customizationService.getCustomization('panelSegmentation.tableMode');
@@ -22581,6 +23158,9 @@ function PanelSegmentation({
22581
23158
  commandsManager.run('addSegment', {
22582
23159
  segmentationId
22583
23160
  });
23161
+ commandsManager.run('setActiveSegmentation', {
23162
+ segmentationId
23163
+ });
22584
23164
  },
22585
23165
  onSegmentClick: (segmentationId, segmentIndex) => {
22586
23166
  commandsManager.run('setActiveSegmentAndCenter', {
@@ -22611,6 +23191,14 @@ function PanelSegmentation({
22611
23191
  segmentIndex
22612
23192
  });
22613
23193
  },
23194
+ onSegmentCopy: segmentationRepresentationType === esm_enums.SegmentationRepresentations.Contour ? (segmentationId, segmentIndex) => {
23195
+ commandsManager.run('copyContourSegment', {
23196
+ sourceSegmentInfo: {
23197
+ segmentationId,
23198
+ segmentIndex
23199
+ }
23200
+ });
23201
+ } : undefined,
22614
23202
  onToggleSegmentVisibility: (segmentationId, segmentIndex, type) => {
22615
23203
  commandsManager.run('toggleSegmentVisibility', {
22616
23204
  segmentationId,
@@ -22702,6 +23290,8 @@ function PanelSegmentation({
22702
23290
  };
22703
23291
 
22704
23292
  // Generate export options
23293
+ // Map each segmentation to an export option for it.
23294
+ // A segmentation is exportable if it has any labelmap or contour data.
22705
23295
  const exportOptions = segmentationsWithRepresentations.map(({
22706
23296
  segmentation
22707
23297
  }) => {
@@ -22710,49 +23300,24 @@ function PanelSegmentation({
22710
23300
  segmentationId
22711
23301
  } = segmentation;
22712
23302
  const {
22713
- Labelmap
23303
+ Labelmap,
23304
+ Contour
22714
23305
  } = representationData;
22715
- if (!Labelmap) {
23306
+ if (!Labelmap && !Contour) {
22716
23307
  return {
22717
23308
  segmentationId,
22718
23309
  isExportable: true
22719
23310
  };
22720
23311
  }
22721
-
22722
- // Check if any segments have anything drawn in any of the viewports
22723
- const hasAnySegmentData = (() => {
22724
- const imageIds = Labelmap.imageIds;
22725
- if (!imageIds?.length) return false;
22726
- for (const imageId of imageIds) {
22727
- const pixelData = esm.cache.getImage(imageId)?.getPixelData();
22728
- if (!pixelData) continue;
22729
- for (let i = 0; i < pixelData.length; i++) {
22730
- if (pixelData[i] !== 0) return true;
22731
- }
22732
- }
22733
- return false;
22734
- })();
22735
- if (!hasAnySegmentData) {
22736
- return {
22737
- segmentationId,
22738
- isExportable: false
22739
- };
22740
- }
22741
- const referencedImageIds = Labelmap.referencedImageIds;
22742
- const firstImageId = referencedImageIds[0];
22743
- const instance = esm.metaData.get('instance', firstImageId);
22744
- if (!instance) {
23312
+ if (!hasExportableLabelMapData(Labelmap, displaySetService) && !hasExportableContourData(Contour)) {
22745
23313
  return {
22746
23314
  segmentationId,
22747
23315
  isExportable: false
22748
23316
  };
22749
23317
  }
22750
- const SOPInstanceUID = instance.SOPInstanceUID || instance.SopInstanceUID;
22751
- const SeriesInstanceUID = instance.SeriesInstanceUID;
22752
- const displaySet = displaySetService.getDisplaySetForSOPInstanceUID(SOPInstanceUID, SeriesInstanceUID);
22753
23318
  return {
22754
23319
  segmentationId,
22755
- isExportable: displaySet?.isReconstructable
23320
+ isExportable: true
22756
23321
  };
22757
23322
  });
22758
23323
 
@@ -22761,14 +23326,29 @@ function PanelSegmentation({
22761
23326
  disabled,
22762
23327
  data: segmentationsWithRepresentations,
22763
23328
  mode: segmentationTableMode,
22764
- title: 'Segmentations',
23329
+ title: `${segmentationRepresentationType ? `${segmentationRepresentationType} ` : ''}Segmentations`,
22765
23330
  exportOptions,
22766
23331
  disableEditing,
22767
23332
  onSegmentationAdd,
22768
23333
  showAddSegment,
22769
23334
  renderInactiveSegmentations: handlers.getRenderInactiveSegmentations(),
23335
+ segmentationRepresentationType,
23336
+ selectedSegmentationIdForType,
22770
23337
  ...handlers
22771
23338
  };
23339
+ const renderUtilitiesToolbar = () => {
23340
+ if (!buttonSection) {
23341
+ return null;
23342
+ }
23343
+ return /*#__PURE__*/react.createElement(ui_next_src/* IconPresentationProvider */.TNf, {
23344
+ size: "large",
23345
+ IconContainer: components_SegmentationUtilityButton
23346
+ }, /*#__PURE__*/react.createElement("div", {
23347
+ className: "flex flex-wrap gap-[3px] bg-transparent pb-[2px] pl-[8px] pt-[6px]"
23348
+ }, /*#__PURE__*/react.createElement(default_src.Toolbar, {
23349
+ buttonSection: buttonSection
23350
+ })));
23351
+ };
22772
23352
  const renderSegments = () => {
22773
23353
  return /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Segments, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.SegmentStatistics.Header, null, /*#__PURE__*/react.createElement(CustomSegmentStatisticsHeader, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.SegmentStatistics.Body, null));
22774
23354
  };
@@ -22776,11 +23356,20 @@ function PanelSegmentation({
22776
23356
  // Render content based on mode
22777
23357
  const renderModeContent = () => {
22778
23358
  if (tableProps.mode === 'collapsed') {
22779
- return /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Header, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.DropdownMenu, null, /*#__PURE__*/react.createElement(CustomDropdownMenuContent, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Selector, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Info, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Content, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentRow, null), renderSegments()));
23359
+ return /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed, null, renderUtilitiesToolbar(), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Header, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.DropdownMenu, null, /*#__PURE__*/react.createElement(CustomDropdownMenuContent, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Selector, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Info, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Collapsed.Content, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentRow, null), renderSegments()));
22780
23360
  }
22781
- return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Header, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.DropdownMenu, null, /*#__PURE__*/react.createElement(CustomDropdownMenuContent, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Label, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Info, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Content, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentRow, null), renderSegments())));
23361
+ return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded, null, renderUtilitiesToolbar(), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Header, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.DropdownMenu, null, /*#__PURE__*/react.createElement(CustomDropdownMenuContent, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Label, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Info, null)), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Expanded.Content, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentRow, null), renderSegments())));
22782
23362
  };
22783
- return /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h, tableProps, children, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Config, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentationRow, null), renderModeContent());
23363
+ return /*#__PURE__*/react.createElement(ui_next_src/* Popover */.AMh, {
23364
+ open: !!activeUtilityOptions,
23365
+ onOpenChange: handlePopoverOpenChange
23366
+ }, /*#__PURE__*/react.createElement(ui_next_src/* PopoverAnchor */.dTQ, null, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h, tableProps, children, /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.Config, null), /*#__PURE__*/react.createElement(ui_next_src/* SegmentationTable */.R4h.AddSegmentationRow, null), renderModeContent())), activeUtilityOptions && /*#__PURE__*/react.createElement(ui_next_src/* PopoverContent */.hlN, {
23367
+ side: "left",
23368
+ align: "start",
23369
+ className: "w-auto"
23370
+ }, /*#__PURE__*/react.createElement(ui_next_src/* ToolSettings */.k_3, {
23371
+ options: activeUtilityOptions
23372
+ })));
22784
23373
  }
22785
23374
  // EXTERNAL MODULE: ../../../node_modules/lodash.debounce/index.js
22786
23375
  var lodash_debounce = __webpack_require__(62051);
@@ -23774,51 +24363,60 @@ function PanelMeasurement(props) {
23774
24363
 
23775
24364
 
23776
24365
 
24366
+
24367
+
24368
+
23777
24369
  const getPanelModule = ({
23778
24370
  commandsManager,
23779
24371
  servicesManager,
23780
24372
  extensionManager
23781
24373
  }) => {
23782
- const wrappedPanelSegmentation = ({
23783
- configuration
23784
- }) => {
24374
+ const {
24375
+ toolbarService
24376
+ } = servicesManager.services;
24377
+ const toolSectionMap = {
24378
+ [esm_enums.SegmentationRepresentations.Labelmap]: toolbarService.sections.labelMapSegmentationToolbox,
24379
+ [esm_enums.SegmentationRepresentations.Contour]: toolbarService.sections.contourSegmentationToolbox
24380
+ };
24381
+ const wrappedPanelSegmentation = props => {
23785
24382
  return /*#__PURE__*/react.createElement(PanelSegmentation, {
23786
24383
  commandsManager: commandsManager,
23787
24384
  servicesManager: servicesManager,
23788
24385
  extensionManager: extensionManager,
23789
24386
  configuration: {
23790
- ...configuration
23791
- }
24387
+ ...props?.configuration
24388
+ },
24389
+ segmentationRepresentationType: props?.segmentationRepresentationType
23792
24390
  });
23793
24391
  };
23794
- const wrappedPanelSegmentationNoHeader = ({
23795
- configuration
23796
- }) => {
24392
+ const wrappedPanelSegmentationNoHeader = props => {
23797
24393
  return /*#__PURE__*/react.createElement(PanelSegmentation, {
23798
24394
  commandsManager: commandsManager,
23799
24395
  servicesManager: servicesManager,
23800
24396
  extensionManager: extensionManager,
23801
24397
  configuration: {
23802
- ...configuration
23803
- }
24398
+ ...props?.configuration
24399
+ },
24400
+ segmentationRepresentationType: props?.segmentationRepresentationType
23804
24401
  });
23805
24402
  };
23806
- const wrappedPanelSegmentationWithTools = ({
23807
- configuration
23808
- }) => {
24403
+ const wrappedPanelSegmentationWithTools = props => {
23809
24404
  const {
23810
- toolbarService
23811
- } = servicesManager.services;
24405
+ t
24406
+ } = (0,es/* useTranslation */.Bd)('SegmentationTable');
24407
+ const tKey = `${props.segmentationRepresentationType ?? 'Segmentation'} tools`;
24408
+ const tValue = t(tKey);
23812
24409
  return /*#__PURE__*/react.createElement(react.Fragment, null, /*#__PURE__*/react.createElement(default_src.Toolbox, {
23813
- buttonSectionId: toolbarService.sections.segmentationToolbox,
23814
- title: "Segmentation Tools"
24410
+ buttonSectionId: toolSectionMap[props.segmentationRepresentationType],
24411
+ title: tValue
23815
24412
  }), /*#__PURE__*/react.createElement(PanelSegmentation, {
23816
24413
  commandsManager: commandsManager,
23817
24414
  servicesManager: servicesManager,
23818
24415
  extensionManager: extensionManager,
23819
24416
  configuration: {
23820
- ...configuration
23821
- }
24417
+ ...props?.configuration
24418
+ },
24419
+ segmentationRepresentationType: props?.segmentationRepresentationType
23822
24420
  }));
23823
24421
  };
23824
24422
  return [{
@@ -23847,11 +24445,23 @@ const getPanelModule = ({
23847
24445
  label: 'Segmentation',
23848
24446
  component: wrappedPanelSegmentationNoHeader
23849
24447
  }, {
23850
- name: 'panelSegmentationWithTools',
24448
+ name: 'panelSegmentationWithToolsLabelMap',
23851
24449
  iconName: 'tab-segmentation',
23852
24450
  iconLabel: 'Segmentation',
23853
- label: 'Segmentation',
23854
- component: wrappedPanelSegmentationWithTools
24451
+ label: i18n_src/* default */.A.t('SegmentationTable:Labelmap'),
24452
+ component: props => wrappedPanelSegmentationWithTools({
24453
+ ...props,
24454
+ segmentationRepresentationType: esm_enums.SegmentationRepresentations.Labelmap
24455
+ })
24456
+ }, {
24457
+ name: 'panelSegmentationWithToolsContour',
24458
+ iconName: 'tab-contours',
24459
+ iconLabel: 'Segmentation',
24460
+ label: i18n_src/* default */.A.t('SegmentationTable:Contour'),
24461
+ component: props => wrappedPanelSegmentationWithTools({
24462
+ ...props,
24463
+ segmentationRepresentationType: esm_enums.SegmentationRepresentations.Contour
24464
+ })
23855
24465
  }];
23856
24466
  };
23857
24467
  /* harmony default export */ const src_getPanelModule = (getPanelModule);
@@ -24065,6 +24675,39 @@ function setupSegmentationModifiedHandler({
24065
24675
  unsubscribe
24066
24676
  };
24067
24677
  }
24678
+
24679
+ /**
24680
+ * Sets up auto tab switching for when the first segmentation is added into the viewer.
24681
+ */
24682
+ function setUpSelectedSegmentationsForViewportHandler({
24683
+ segmentationService
24684
+ }) {
24685
+ const selectedSegmentationsForViewportEvents = [segmentationService.EVENTS.SEGMENTATION_MODIFIED, segmentationService.EVENTS.SEGMENTATION_REPRESENTATION_MODIFIED];
24686
+ const unsubscribeSelectedSegmentationsForViewportEvents = selectedSegmentationsForViewportEvents.map(eventName => segmentationService.subscribe(eventName, event => {
24687
+ const {
24688
+ viewportId
24689
+ } = event;
24690
+ if (!viewportId) {
24691
+ return;
24692
+ }
24693
+ const {
24694
+ selectedSegmentationsForViewport,
24695
+ setSelectedSegmentationsForViewport
24696
+ } = useSelectedSegmentationsForViewportStore.getState();
24697
+ const representations = segmentationService.getSegmentationRepresentations(viewportId);
24698
+ const activeRepresentation = representations.find(representation => representation.active);
24699
+ const typeToSegmentationIdMap = selectedSegmentationsForViewport[viewportId] ?? new Map();
24700
+ if (activeRepresentation) {
24701
+ typeToSegmentationIdMap.set(activeRepresentation.type, activeRepresentation.segmentationId);
24702
+ } else {
24703
+ typeToSegmentationIdMap.clear();
24704
+ }
24705
+ setSelectedSegmentationsForViewport(viewportId, typeToSegmentationIdMap);
24706
+ })).map(subscription => subscription.unsubscribe);
24707
+ return {
24708
+ unsubscribeSelectedSegmentationsForViewportEvents
24709
+ };
24710
+ }
24068
24711
  ;// ../../../extensions/cornerstone/src/utils/promptHydrationDialog.ts
24069
24712
  const HydrationType = {
24070
24713
  SEG: 'SEG',
@@ -24219,13 +24862,15 @@ function _askHydrate(uiViewportDialogService, customizationService, viewportId,
24219
24862
 
24220
24863
 
24221
24864
 
24865
+
24222
24866
  const utils_utils = {
24223
24867
  handleSegmentChange: handleSegmentChange,
24224
24868
  isReferenceViewable: isReferenceViewable,
24225
24869
  setupSegmentationDataModifiedHandler: setupSegmentationDataModifiedHandler,
24226
24870
  setupSegmentationModifiedHandler: setupSegmentationModifiedHandler,
24227
24871
  promptHydrationDialog: utils_promptHydrationDialog,
24228
- getCenterExtent: getCenterExtent
24872
+ getCenterExtent: getCenterExtent,
24873
+ createSegmentationForViewport: createSegmentationForViewport
24229
24874
  };
24230
24875
  /* harmony default export */ const src_utils = (utils_utils);
24231
24876
  ;// ../../../extensions/cornerstone/src/utils/setUpSegmentationEventHandlers.ts
@@ -24263,7 +24908,7 @@ const setUpSegmentationEventHandlers = ({
24263
24908
  }
24264
24909
  const segmentation = segmentationService.getSegmentation(segmentationId);
24265
24910
  const label = segmentation.cachedStats.info;
24266
- const imageIds = segmentation.representationData.Labelmap.imageIds;
24911
+ const imageIds = segmentation.representationData?.Labelmap?.imageIds ?? segmentation.representationData?.Contour?.imageIds;
24267
24912
 
24268
24913
  // Create a display set for the segmentation
24269
24914
  const segmentationDisplaySet = {
@@ -24282,7 +24927,12 @@ const setUpSegmentationEventHandlers = ({
24282
24927
  };
24283
24928
  displaySetService.addDisplaySets(segmentationDisplaySet);
24284
24929
  });
24285
- const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated];
24930
+ const {
24931
+ unsubscribeSelectedSegmentationsForViewportEvents
24932
+ } = setUpSelectedSegmentationsForViewportHandler({
24933
+ segmentationService
24934
+ });
24935
+ const unsubscriptions = [unsubscribeSegmentationDataModifiedHandler, unsubscribeSegmentationModifiedHandler, unsubscribeSegmentationCreated, ...unsubscribeSelectedSegmentationsForViewportEvents];
24286
24936
  return {
24287
24937
  unsubscriptions
24288
24938
  };
@@ -24693,7 +25343,7 @@ const cornerstoneExtension = {
24693
25343
  });
24694
25344
  unsubscriptions.push(...segmentationUnsubscriptions);
24695
25345
  toolbarService.registerEventForToolbarUpdate(cornerstoneViewportService, [cornerstoneViewportService.EVENTS.VIEWPORT_DATA_CHANGED]);
24696
- toolbarService.registerEventForToolbarUpdate(segmentationService, [segmentationService.EVENTS.SEGMENTATION_REMOVED, segmentationService.EVENTS.SEGMENTATION_MODIFIED]);
25346
+ toolbarService.registerEventForToolbarUpdate(segmentationService, [segmentationService.EVENTS.SEGMENTATION_REMOVED, segmentationService.EVENTS.SEGMENTATION_MODIFIED, segmentationService.EVENTS.ANNOTATION_CUT_MERGE_PROCESS_COMPLETED]);
24697
25347
  toolbarService.registerEventForToolbarUpdate(esm.eventTarget, [dist_esm.Enums.Events.TOOL_ACTIVATED]);
24698
25348
 
24699
25349
  // Configure the interleaved/HTJ2K loader
@@ -24732,6 +25382,7 @@ const cornerstoneExtension = {
24732
25382
  useSynchronizersStore/* useSynchronizersStore */.U.getState().clearSynchronizersStore();
24733
25383
  default_src.useToggleOneUpViewportGridStore.getState().clearToggleOneUpViewportGridStore();
24734
25384
  useSegmentationPresentationStore/* useSegmentationPresentationStore */.v.getState().clearSegmentationPresentationStore();
25385
+ useSelectedSegmentationsForViewportStore.getState().clearSelectedSegmentationsForViewportStore();
24735
25386
  segmentationService.removeAllSegmentations();
24736
25387
  },
24737
25388
  /**